diff --git a/services/ptable_parse/ptable.h b/services/ptable_parse/ptable.h index f0e724c5ddabb65592cccc40a11918581526ab64..0fc8c5dd5fc6942b81556e851d7782e41b48bc87 100644 --- a/services/ptable_parse/ptable.h +++ b/services/ptable_parse/ptable.h @@ -35,6 +35,8 @@ public: uint64_t partitionSize {}; uint8_t partitionTypeGuid[GPT_PARTITION_TYPE_GUID_LEN] {}; uint32_t lun {}; + int gptEntryBufOffset {}; + bool isTailPart {false}; std::string dispName {}; std::string writeMode {"WRITE_RAW"}; std::string writePath {}; @@ -64,6 +66,31 @@ public: virtual bool EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector &modifyList) = 0; virtual bool GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize) = 0; virtual void AddChildPtable(std::unique_ptr child) {} + virtual bool CorrectBufByPtnList(uint8_t *imageBuf, uint64_t imgBufSize, const std::vector &srcInfo, + const std::vector &dstInfo) + { + return false; + } + + int GetEndPtnIndex() + { + return endPtnIndex_; + } + + int GetUsrDataPtnIndex() + { + return usrDataPtnIndex_; + } + + void SetUsrDataPtnIndex(int usrDataPtnIndex) + { + usrDataPtnIndex_ = usrDataPtnIndex; + } + + bool HasTailPart() + { + return hasTailpart_; + } #ifndef UPDATER_UT protected: @@ -161,6 +188,11 @@ public: PtableData ptableData_; uint64_t reservedSize_ {0}; + int startPtnIndex_ {-1}; + int endPtnIndex_ {-1}; + int usrDataPtnIndex_ {-1}; + bool hasTailpart_ {false}; + PtableData GetPtableData() const; bool MemReadWithOffset(const std::string &filePath, const uint64_t offset, uint8_t *outData, const uint32_t dataSize); diff --git a/services/ptable_parse/ufs_ptable.cpp b/services/ptable_parse/ufs_ptable.cpp index d7d686f4f6eaf6cef8f2115841277e3d6f50a414..6ab0839a741876bef5866ae9ed9fba4193ff419c 100644 --- a/services/ptable_parse/ufs_ptable.cpp +++ b/services/ptable_parse/ufs_ptable.cpp @@ -157,12 +157,19 @@ bool UfsPtable::UfsReadGpt(const uint8_t *gptImage, const uint32_t len, } it++; } + UfsReadGptEntry(gptImage, lun, blockSize, startIter); + return true; +} +void UfsPtable::UfsReadGptEntry(const uint8_t *gptImage, const uint32_t lun, + const uint32_t blockSize, std::vector::iterator startIter) +{ uint32_t partEntryCnt = blockSize / PARTITION_ENTRY_SIZE; uint32_t partition0 = GET_LLWORD_FROM_BYTE(gptImage + blockSize + PARTITION_ENTRIES_OFFSET); uint32_t count = 0; const uint8_t *data = nullptr; + bool tailPartFlag = false; for (uint32_t i = 0; i < (MAX_PARTITION_NUM / partEntryCnt) && count < MAX_PARTITION_NUM; i++) { data = gptImage + (partition0 + i) * blockSize; for (uint32_t j = 0; j < partEntryCnt; j++) { @@ -187,15 +194,26 @@ bool UfsPtable::UfsReadGpt(const uint8_t *gptImage, const uint32_t len, ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, newPtnInfo.dispName, MAX_GPT_NAME_SIZE / 2); (void)memcpy_s(newPtnInfo.partitionTypeGuid, sizeof(newPtnInfo.partitionTypeGuid), typeGuid, sizeof(typeGuid)); + newPtnInfo.isTailPart = tailPartFlag; newPtnInfo.lun = lun; + // 2 : pmbr and gpt header + newPtnInfo.gptEntryBufOffset = (partition0 + i) * blockSize + j * PARTITION_ENTRY_SIZE - 2 * blockSize; + if (newPtnInfo.dispName == USERDATA_PARTITION) { + tailPartFlag = true; + usrDataPtnIndex_ = std::distance(partitionInfo_.begin(), startIter); + } startIter = ++(partitionInfo_.insert(startIter, newPtnInfo)); count++; } } - return true; + if (tailPartFlag) { + endPtnIndex_ = static_cast(std::distance(partitionInfo_.begin(), startIter)) - 1; + startPtnIndex_ = endPtnIndex_ + 1 - count; + hasTailpart_ = partitionInfo_[endPtnIndex_].isTailPart; + } + return; } - void UfsPtable::UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize) { uint32_t deviceBlockSize = GetDeviceBlockSize(); @@ -275,7 +293,7 @@ bool UfsPtable::ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t i SetDeviceLunNum(); LOG(INFO) << "lun number of ptable:" << deviceLunNum_; - + ufsPtnDataInfo_.clear(); for (uint32_t i = 0; i < deviceLunNum_; i++) { UfsPartitionDataInfo newLunPtnDataInfo; (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE); @@ -507,6 +525,46 @@ uint8_t *UfsPtable::GetPtableImageUfsLunEntryStart(uint8_t *imageBuf, const uint return imageBuf + entryStart; } +bool UfsPtable::CorrectBufByPtnList(uint8_t *imageBuf, uint64_t imgBufSize, const std::vector &srcInfo, + const std::vector &dstInfo) +{ + if (imageBuf == nullptr || imgBufSize == 0 || srcInfo.size() != dstInfo.size()) { + LOG(ERROR) << "invalid input. imgBufSize : " << imgBufSize << " srcInfo.size: " << srcInfo.size() + << " dstInfo.size:" << dstInfo.size(); + return false; + } + if (usrDataPtnIndex_ < 0 || endPtnIndex_ < 0 || usrDataPtnIndex_ >= dstInfo.size() + || endPtnIndex_ >= dstInfo.size()) { + LOG(ERROR) << "invaild dst ptn info list"; + return false; + } + uint8_t* ufsLunEntryStart = GetPtableImageUfsLunEntryStart(imageBuf, dstInfo[usrDataPtnIndex_].lun); + const uint32_t editLen = PARTITION_ENTRY_SIZE * MAX_PARTITION_NUM; + std::vector newBuf(ufsLunEntryStart, ufsLunEntryStart + editLen); + for (int i = startPtnIndex_; i <= endPtnIndex_; i++) { + if (srcInfo[i].startAddr == dstInfo[i].startAddr && srcInfo[i].partitionSize == dstInfo[i].partitionSize + && srcInfo[i].dispName == dstInfo[i].dispName) { + continue; + } + LOG(INFO) << srcInfo[i].dispName << "should adjust"; + std::vector newEntryBuf(ufsLunEntryStart + dstInfo[i].gptEntryBufOffset, + ufsLunEntryStart + dstInfo[i].gptEntryBufOffset + PARTITION_ENTRY_SIZE); + PUT_LONG_LONG(newEntryBuf.data() + FIRST_LBA_OFFSET, dstInfo[i].startAddr / GetDeviceBlockSize()); + PUT_LONG_LONG(newEntryBuf.data() + LAST_LBA_OFFSET, + (dstInfo[i].startAddr + dstInfo[i].partitionSize) / GetDeviceBlockSize() - 1); + if (srcInfo[i].gptEntryBufOffset > editLen - PARTITION_ENTRY_SIZE) { + LOG(ERROR) << "srcInfo[" << i << "] error. gptEntryBufOffset = " << srcInfo[i].gptEntryBufOffset; + return false; + } + std::copy(newEntryBuf.begin(), newEntryBuf.end(), newBuf.begin() + srcInfo[i].gptEntryBufOffset); + } + if (memcpy_s(ufsLunEntryStart, imgBufSize - (ufsLunEntryStart - imageBuf), newBuf.data(), editLen) != 0) { + LOG(ERROR) << "memcpy fail. destSize :" << imgBufSize - (ufsLunEntryStart - imageBuf); + return false; + } + return true; +} + bool UfsPtable::EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector &modifyList) { if (imageBuf == nullptr || imgBufSize == 0 || modifyList.empty() || ptableData_.blockSize == 0) { diff --git a/services/ptable_parse/ufs_ptable.h b/services/ptable_parse/ufs_ptable.h index 16a379f3c923e3bb52a5b06871219ebd44c1d7d9..a3cde0e3eca82691786a67182e593962a57b50f8 100644 --- a/services/ptable_parse/ufs_ptable.h +++ b/services/ptable_parse/ufs_ptable.h @@ -31,7 +31,8 @@ public: bool WritePartitionTable() override; bool EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector &modifyList) override; bool GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize) override; - + bool CorrectBufByPtnList(uint8_t *imageBuf, uint64_t imgBufSize, const std::vector &srcInfo, + const std::vector &dstInfo) override; #ifndef UPDATER_UT protected: #else @@ -69,6 +70,8 @@ public: #endif bool WriteBackupPartitionTable(uint32_t lunIdx, uint64_t lunSize); bool UfsReadGpt(const uint8_t *gptImage, const uint32_t len, const uint32_t lun, const uint32_t blockSize); + void UfsReadGptEntry(const uint8_t *gptImage, const uint32_t lun, + const uint32_t blockSize, std::vector::iterator startIter); bool ParseGptHeaderByUfsLun(const uint8_t *gptImage, const uint32_t len, const uint32_t lun, const uint32_t blockSize); void UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize); diff --git a/services/updater.cpp b/services/updater.cpp index e77d447bc9f39948dc59497d21d35527ba5910d7..f54a6cf365222afd081a51c56b87b122cd6d17d7 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -113,9 +113,14 @@ UpdaterStatus IsSpaceCapacitySufficient(const UpdaterParams &upParams) return UPDATE_ERROR; } uint64_t maxStashSize = *max_element(stashSizeList.begin(), stashSizeList.end()); - LOG(INFO) << "get max stash size:" << maxStashSize; + LOG(INFO) << "get max stash size: " << maxStashSize; uint64_t totalPkgSize = maxStashSize + MIN_UPDATE_SPACE; - + uint64_t shrinkSize = 0; + if (!upParams.virtualShrinkInfo.empty() && + Utils::ConvertToUnsignedLongLong(upParams.virtualShrinkInfo, shrinkSize)) { + totalPkgSize += shrinkSize * 3 / 2; // 3 / 2 = 1.5 + } + LOG(INFO) << "needed totalPkgSize = " << totalPkgSize; if (CheckStatvfs(totalPkgSize) != UPDATE_SUCCESS) { LOG(ERROR) << "CheckStatvfs error"; UPDATER_LAST_WORD(UPDATE_ERROR); diff --git a/utils/include/utils.h b/utils/include/utils.h index ac00bb64df08b77224ba549cbaa062312f4e18d4..0074fceb6c3d86618795a67258916680475dbb90 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -103,6 +103,7 @@ void TrimString (std::string &str); bool RestoreconPath(const std::string &path); std::string TrimUpdateMode(const std::string &mode); bool IsEsDevice(); +bool ConvertToUnsignedLongLong(const std::string &str, uint64_t &value); bool ConvertToLongLong(const std::string &str, int64_t &value); bool ConvertToLong(const std::string &str, int32_t &value); bool ConvertToUnsignedLong(const std::string &str, uint32_t &value); diff --git a/utils/utils.cpp b/utils/utils.cpp index 51b8ea41931ea4de08f5ca05d8662437ef14643f..0fdf150daebf37a9b3c727978cb1898ced505591 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -962,6 +962,21 @@ bool IsEsDevice() return true; } +bool ConvertToUnsignedLongLong(const std::string &str, uint64_t &value) +{ + char *endPtr = nullptr; + errno = 0; + + value = std::strtoull(str.c_str(), &endPtr, 0); +#ifndef UPDATER_UT + if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) { + LOG(ERROR) << "Convert string to uint64_t failed, str " << str << " converted to value " << value; + return false; + } +#endif + return true; +} + bool ConvertToLongLong(const std::string &str, int64_t &value) { char *endPtr = nullptr;