1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include "update_partitions.h" 16fb299fa2Sopenharmony_ci#include <cerrno> 17fb299fa2Sopenharmony_ci#include <cstdio> 18fb299fa2Sopenharmony_ci#include <sstream> 19fb299fa2Sopenharmony_ci#include <string> 20fb299fa2Sopenharmony_ci#include "log/dump.h" 21fb299fa2Sopenharmony_ci#include "log/log.h" 22fb299fa2Sopenharmony_ci#include "updater/updater_const.h" 23fb299fa2Sopenharmony_ci#include "utils.h" 24fb299fa2Sopenharmony_ci 25fb299fa2Sopenharmony_ciusing namespace std; 26fb299fa2Sopenharmony_ciusing namespace Uscript; 27fb299fa2Sopenharmony_ciusing namespace Hpackage; 28fb299fa2Sopenharmony_ciusing namespace Updater; 29fb299fa2Sopenharmony_ciconstexpr int MIN_PARTITIONS_NUM = 2; 30fb299fa2Sopenharmony_ciconstexpr int MAX_PARTITIONS_NUM = 20; 31fb299fa2Sopenharmony_cinamespace Updater { 32fb299fa2Sopenharmony_cistatic bool CheckValueInt(const cJSON *item) 33fb299fa2Sopenharmony_ci{ 34fb299fa2Sopenharmony_ci if (item == nullptr || !cJSON_IsNumber(item)) { 35fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get valueint"; 36fb299fa2Sopenharmony_ci return false; 37fb299fa2Sopenharmony_ci } 38fb299fa2Sopenharmony_ci return true; 39fb299fa2Sopenharmony_ci} 40fb299fa2Sopenharmony_ci 41fb299fa2Sopenharmony_cistatic bool CheckValueString(const cJSON *item) 42fb299fa2Sopenharmony_ci{ 43fb299fa2Sopenharmony_ci if (item == nullptr || !cJSON_IsString(item) || strlen(item->valuestring) == 0) { 44fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get valuestring"; 45fb299fa2Sopenharmony_ci return false; 46fb299fa2Sopenharmony_ci } 47fb299fa2Sopenharmony_ci return true; 48fb299fa2Sopenharmony_ci} 49fb299fa2Sopenharmony_ci 50fb299fa2Sopenharmony_cibool UpdatePartitions::SetPartitionInfo(const cJSON *partitions, int idx, struct Partition *myPartition) const 51fb299fa2Sopenharmony_ci{ 52fb299fa2Sopenharmony_ci cJSON *thisPartition = cJSON_GetArrayItem(partitions, idx); 53fb299fa2Sopenharmony_ci if (thisPartition == nullptr) { 54fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get thisPartion: " << idx; 55fb299fa2Sopenharmony_ci return false; 56fb299fa2Sopenharmony_ci } 57fb299fa2Sopenharmony_ci cJSON *item = cJSON_GetObjectItem(thisPartition, "start"); 58fb299fa2Sopenharmony_ci if (!CheckValueInt(item)) { 59fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get start"; 60fb299fa2Sopenharmony_ci return false; 61fb299fa2Sopenharmony_ci } 62fb299fa2Sopenharmony_ci myPartition->start = static_cast<size_t>(item->valueint); 63fb299fa2Sopenharmony_ci 64fb299fa2Sopenharmony_ci item = cJSON_GetObjectItem(thisPartition, "length"); 65fb299fa2Sopenharmony_ci if (!CheckValueInt(item)) { 66fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get length"; 67fb299fa2Sopenharmony_ci return false; 68fb299fa2Sopenharmony_ci } 69fb299fa2Sopenharmony_ci myPartition->length = static_cast<size_t>(item->valueint); 70fb299fa2Sopenharmony_ci myPartition->partNum = 0; 71fb299fa2Sopenharmony_ci myPartition->devName = "mmcblk0px"; 72fb299fa2Sopenharmony_ci 73fb299fa2Sopenharmony_ci item = cJSON_GetObjectItem(thisPartition, "partName"); 74fb299fa2Sopenharmony_ci if (!CheckValueString(item)) { 75fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get partName"; 76fb299fa2Sopenharmony_ci return false; 77fb299fa2Sopenharmony_ci } 78fb299fa2Sopenharmony_ci myPartition->partName = (item->valuestring); 79fb299fa2Sopenharmony_ci 80fb299fa2Sopenharmony_ci item = cJSON_GetObjectItem(thisPartition, "fsType"); 81fb299fa2Sopenharmony_ci if (!CheckValueString(item)) { 82fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get fsType"; 83fb299fa2Sopenharmony_ci return false; 84fb299fa2Sopenharmony_ci } 85fb299fa2Sopenharmony_ci myPartition->fsType = (item->valuestring); 86fb299fa2Sopenharmony_ci 87fb299fa2Sopenharmony_ci LOG(INFO) << "<start> <length> <devname> <partname> <fstype>"; 88fb299fa2Sopenharmony_ci LOG(INFO) << myPartition->start << " " << myPartition->length << " " << myPartition->devName << " " << 89fb299fa2Sopenharmony_ci myPartition->partName << " " << myPartition->fsType; 90fb299fa2Sopenharmony_ci return true; 91fb299fa2Sopenharmony_ci} 92fb299fa2Sopenharmony_ci 93fb299fa2Sopenharmony_ciint UpdatePartitions::ParsePartitionInfo(const std::string &partitionInfo, PartitonList &newPartList) const 94fb299fa2Sopenharmony_ci{ 95fb299fa2Sopenharmony_ci cJSON* root = cJSON_Parse(partitionInfo.c_str()); 96fb299fa2Sopenharmony_ci if (root == nullptr) { 97fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get root"; 98fb299fa2Sopenharmony_ci return -1; 99fb299fa2Sopenharmony_ci } 100fb299fa2Sopenharmony_ci cJSON* partitions = cJSON_GetObjectItem(root, "Partition"); 101fb299fa2Sopenharmony_ci if (partitions == nullptr) { 102fb299fa2Sopenharmony_ci LOG(ERROR) << "Error get Partitions"; 103fb299fa2Sopenharmony_ci cJSON_Delete(root); 104fb299fa2Sopenharmony_ci return -1; 105fb299fa2Sopenharmony_ci } 106fb299fa2Sopenharmony_ci int number = cJSON_GetArraySize(partitions); 107fb299fa2Sopenharmony_ci if (number <= MIN_PARTITIONS_NUM || number >= MAX_PARTITIONS_NUM) { 108fb299fa2Sopenharmony_ci LOG(ERROR) << "Error partitions number: " << number; 109fb299fa2Sopenharmony_ci cJSON_Delete(root); 110fb299fa2Sopenharmony_ci return -1; 111fb299fa2Sopenharmony_ci } 112fb299fa2Sopenharmony_ci LOG(INFO) << "Partitions numbers " << number; 113fb299fa2Sopenharmony_ci 114fb299fa2Sopenharmony_ci for (int i = 0; i < number; i++) { 115fb299fa2Sopenharmony_ci struct Partition* myPartition = static_cast<struct Partition*>(calloc(1, sizeof(struct Partition))); 116fb299fa2Sopenharmony_ci if (!myPartition) { 117fb299fa2Sopenharmony_ci LOG(ERROR) << "Allocate memory for partition failed: " << errno; 118fb299fa2Sopenharmony_ci cJSON_Delete(root); 119fb299fa2Sopenharmony_ci return 0; 120fb299fa2Sopenharmony_ci } 121fb299fa2Sopenharmony_ci if (!SetPartitionInfo(partitions, i, myPartition)) { 122fb299fa2Sopenharmony_ci free(myPartition); 123fb299fa2Sopenharmony_ci myPartition = nullptr; 124fb299fa2Sopenharmony_ci break; 125fb299fa2Sopenharmony_ci } 126fb299fa2Sopenharmony_ci newPartList.push_back(myPartition); 127fb299fa2Sopenharmony_ci } 128fb299fa2Sopenharmony_ci cJSON_Delete(root); 129fb299fa2Sopenharmony_ci return 1; 130fb299fa2Sopenharmony_ci} 131fb299fa2Sopenharmony_ci 132fb299fa2Sopenharmony_ciint UpdatePartitions::DoNewPartitions(PartitonList &newPartList) 133fb299fa2Sopenharmony_ci{ 134fb299fa2Sopenharmony_ci int ret = DoPartitions(newPartList); 135fb299fa2Sopenharmony_ci newPartList.clear(); 136fb299fa2Sopenharmony_ci if (ret <= 0) { 137fb299fa2Sopenharmony_ci LOG(INFO) << "do_partitions FAIL "; 138fb299fa2Sopenharmony_ci } else if (ret == 1) { 139fb299fa2Sopenharmony_ci LOG(INFO) << "partitions not changed,Skip."; 140fb299fa2Sopenharmony_ci } else if (ret > 1) { 141fb299fa2Sopenharmony_ci LOG(INFO) << "do_partitions success reboot"; 142fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 143fb299fa2Sopenharmony_ci Utils::UpdaterDoReboot("updater", "Updater finish do new partitions"); 144fb299fa2Sopenharmony_ci#endif 145fb299fa2Sopenharmony_ci } 146fb299fa2Sopenharmony_ci return ret; 147fb299fa2Sopenharmony_ci} 148fb299fa2Sopenharmony_ci 149fb299fa2Sopenharmony_ciint UpdatePartitions::SetNewPartition(const std::string &filePath, const FileInfo *info, Uscript::UScriptEnv &env) 150fb299fa2Sopenharmony_ci{ 151fb299fa2Sopenharmony_ci std::string tmpPath = "/data/updater" + filePath; 152fb299fa2Sopenharmony_ci char realPath[PATH_MAX + 1] = {}; 153fb299fa2Sopenharmony_ci if (realpath(tmpPath.c_str(), realPath) == nullptr) { 154fb299fa2Sopenharmony_ci LOG(ERROR) << "Error to create: " << tmpPath; 155fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 156fb299fa2Sopenharmony_ci } 157fb299fa2Sopenharmony_ci Hpackage::PkgManager::StreamPtr outStream = nullptr; 158fb299fa2Sopenharmony_ci int ret = env.GetPkgManager()->CreatePkgStream(outStream, 159fb299fa2Sopenharmony_ci std::string(realPath), info->unpackedSize, PkgStream::PkgStreamType_Write); 160fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS || outStream == nullptr) { 161fb299fa2Sopenharmony_ci LOG(ERROR) << "Error to create output stream"; 162fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 163fb299fa2Sopenharmony_ci } 164fb299fa2Sopenharmony_ci ret = env.GetPkgManager()->ExtractFile(filePath, outStream); 165fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 166fb299fa2Sopenharmony_ci LOG(ERROR) << "Error to extract file"; 167fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 168fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 169fb299fa2Sopenharmony_ci } 170fb299fa2Sopenharmony_ci FILE *fp = fopen(realPath, "rb"); 171fb299fa2Sopenharmony_ci if (!fp) { 172fb299fa2Sopenharmony_ci LOG(ERROR) << "Open " << tmpPath << " failed: " << errno; 173fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 174fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 175fb299fa2Sopenharmony_ci } 176fb299fa2Sopenharmony_ci char partitionInfo[MAX_LOG_BUF_SIZE]; 177fb299fa2Sopenharmony_ci size_t partitionCount = fread(partitionInfo, 1, MAX_LOG_BUF_SIZE, fp); 178fb299fa2Sopenharmony_ci fclose(fp); 179fb299fa2Sopenharmony_ci if (partitionCount <= LEAST_PARTITION_COUNT) { 180fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 181fb299fa2Sopenharmony_ci LOG(ERROR) << "Invalid partition size, too small"; 182fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 183fb299fa2Sopenharmony_ci } 184fb299fa2Sopenharmony_ci PartitonList newPartList {}; 185fb299fa2Sopenharmony_ci if (ParsePartitionInfo(std::string(partitionInfo), newPartList) == 0) { 186fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 187fb299fa2Sopenharmony_ci return USCRIPT_ABOART; 188fb299fa2Sopenharmony_ci } 189fb299fa2Sopenharmony_ci if (newPartList.empty()) { 190fb299fa2Sopenharmony_ci LOG(ERROR) << "Partition is empty "; 191fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 192fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; // Partitions table is empty not require partition. 193fb299fa2Sopenharmony_ci } 194fb299fa2Sopenharmony_ci DoNewPartitions(newPartList); 195fb299fa2Sopenharmony_ci env.GetPkgManager()->ClosePkgStream(outStream); 196fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; 197fb299fa2Sopenharmony_ci} 198fb299fa2Sopenharmony_ci 199fb299fa2Sopenharmony_ciint32_t UpdatePartitions::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context) 200fb299fa2Sopenharmony_ci{ 201fb299fa2Sopenharmony_ci LOG(INFO) << "enter UpdatePartitions::Execute "; 202fb299fa2Sopenharmony_ci if (context.GetParamCount() != 1) { 203fb299fa2Sopenharmony_ci LOG(ERROR) << "Invalid UpdatePartitions::Execute param"; 204fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 205fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 206fb299fa2Sopenharmony_ci } 207fb299fa2Sopenharmony_ci std::string filePath; 208fb299fa2Sopenharmony_ci int32_t ret = context.GetParam(0, filePath); 209fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 210fb299fa2Sopenharmony_ci LOG(ERROR) << "Fail to get filePath"; 211fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 212fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 213fb299fa2Sopenharmony_ci } else { 214fb299fa2Sopenharmony_ci LOG(INFO) << "UpdatePartitions::Execute filePath " << filePath; 215fb299fa2Sopenharmony_ci } 216fb299fa2Sopenharmony_ci const FileInfo *info = env.GetPkgManager()->GetFileInfo(filePath); 217fb299fa2Sopenharmony_ci if (info == nullptr) { 218fb299fa2Sopenharmony_ci LOG(ERROR) << "Error to get file info"; 219fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 220fb299fa2Sopenharmony_ci return USCRIPT_ERROR_EXECUTE; 221fb299fa2Sopenharmony_ci } 222fb299fa2Sopenharmony_ci return SetNewPartition(filePath, info, env); 223fb299fa2Sopenharmony_ci} 224fb299fa2Sopenharmony_ci} // namespace Updater 225