1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2022 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
16fb299fa2Sopenharmony_ci#include "ptable.h"
17fb299fa2Sopenharmony_ci
18fb299fa2Sopenharmony_ci#include <algorithm>
19fb299fa2Sopenharmony_ci#include <map>
20fb299fa2Sopenharmony_ci#include <sys/stat.h>
21fb299fa2Sopenharmony_ci
22fb299fa2Sopenharmony_ci#include "applypatch/data_writer.h"
23fb299fa2Sopenharmony_ci#include "log/log.h"
24fb299fa2Sopenharmony_ci#include "securec.h"
25fb299fa2Sopenharmony_ci
26fb299fa2Sopenharmony_cinamespace Updater {
27fb299fa2Sopenharmony_ciconstexpr const char *PTABLE_CONFIG_PATH = "/etc/ptable_data.json";
28fb299fa2Sopenharmony_ciconstexpr const char *PTABLE_DATA_LABEL = "ptableData";
29fb299fa2Sopenharmony_ciconstexpr const char *EMMC_GPT_DATA_LEN_LABEL = "emmcGptDataLen";
30fb299fa2Sopenharmony_ciconstexpr const char *LBA_LEN_LABEL = "lbaLen";
31fb299fa2Sopenharmony_ciconstexpr const char *GPT_HEADER_LEN_LABEL = "gptHeaderLen";
32fb299fa2Sopenharmony_ciconstexpr const char *BLOCK_SIZE_LABEL = "blockSize";
33fb299fa2Sopenharmony_ciconstexpr const char *IMG_LUN_SIZE_LABEL = "imgLuSize";
34fb299fa2Sopenharmony_ciconstexpr const char *START_LUN_NUM_LABEL = "startLunNumber";
35fb299fa2Sopenharmony_ciconstexpr const char *WRITE_DEVICE_LUN_SIZE_LABEL = "writeDeviceLunSize";
36fb299fa2Sopenharmony_ciconstexpr const char *DEFAULT_LUN_NUM_LABEL = "defaultLunNum";
37fb299fa2Sopenharmony_ci
38fb299fa2Sopenharmony_cistd::vector<Ptable::PtnInfo> Ptable::GetPtablePartitionInfo() const
39fb299fa2Sopenharmony_ci{
40fb299fa2Sopenharmony_ci    return partitionInfo_;
41fb299fa2Sopenharmony_ci}
42fb299fa2Sopenharmony_ci
43fb299fa2Sopenharmony_ciuint32_t Ptable::GetPtablePartitionNum() const
44fb299fa2Sopenharmony_ci{
45fb299fa2Sopenharmony_ci    return partitionInfo_.size();
46fb299fa2Sopenharmony_ci}
47fb299fa2Sopenharmony_ci
48fb299fa2Sopenharmony_cibool Ptable::LoadPtnInfo(const std::vector<PtnInfo> &ptnInfo)
49fb299fa2Sopenharmony_ci{
50fb299fa2Sopenharmony_ci    if (ptnInfo.empty()) {
51fb299fa2Sopenharmony_ci        LOG(ERROR) << "ptnInfo is empty";
52fb299fa2Sopenharmony_ci        return false;
53fb299fa2Sopenharmony_ci    }
54fb299fa2Sopenharmony_ci    partitionInfo_ = ptnInfo;
55fb299fa2Sopenharmony_ci    return true;
56fb299fa2Sopenharmony_ci}
57fb299fa2Sopenharmony_ci
58fb299fa2Sopenharmony_civoid Ptable::SetReservedSize(uint64_t reservedSize)
59fb299fa2Sopenharmony_ci{
60fb299fa2Sopenharmony_ci    reservedSize_ = reservedSize;
61fb299fa2Sopenharmony_ci}
62fb299fa2Sopenharmony_ci
63fb299fa2Sopenharmony_cistd::vector<Ptable::PtnInfo>& Ptable::GetPtablePartitionInfoInstance()
64fb299fa2Sopenharmony_ci{
65fb299fa2Sopenharmony_ci    return partitionInfo_;
66fb299fa2Sopenharmony_ci}
67fb299fa2Sopenharmony_ci
68fb299fa2Sopenharmony_cibool Ptable::InitPtable()
69fb299fa2Sopenharmony_ci{
70fb299fa2Sopenharmony_ci    if (!partitionInfo_.empty()) {
71fb299fa2Sopenharmony_ci        std::vector<PtnInfo>().swap(partitionInfo_);
72fb299fa2Sopenharmony_ci    }
73fb299fa2Sopenharmony_ci    if (!ParsePtableData()) {
74fb299fa2Sopenharmony_ci        LOG(ERROR) << "parse PtableData from json file error";
75fb299fa2Sopenharmony_ci        return false;
76fb299fa2Sopenharmony_ci    }
77fb299fa2Sopenharmony_ci    return true;
78fb299fa2Sopenharmony_ci}
79fb299fa2Sopenharmony_ci
80fb299fa2Sopenharmony_cibool Ptable::ParsePtableDataNode(const JsonNode &ptableDataNode)
81fb299fa2Sopenharmony_ci{
82fb299fa2Sopenharmony_ci    std::map<std::string, uint32_t*> ptableDataVars = {
83fb299fa2Sopenharmony_ci        {EMMC_GPT_DATA_LEN_LABEL, &ptableData_.emmcGptDataLen},
84fb299fa2Sopenharmony_ci        {LBA_LEN_LABEL, &ptableData_.lbaLen},
85fb299fa2Sopenharmony_ci        {GPT_HEADER_LEN_LABEL, &ptableData_.gptHeaderLen},
86fb299fa2Sopenharmony_ci        {BLOCK_SIZE_LABEL, &ptableData_.blockSize},
87fb299fa2Sopenharmony_ci        {IMG_LUN_SIZE_LABEL, &ptableData_.imgLuSize},
88fb299fa2Sopenharmony_ci        {START_LUN_NUM_LABEL, &ptableData_.startLunNumber},
89fb299fa2Sopenharmony_ci        {WRITE_DEVICE_LUN_SIZE_LABEL, &ptableData_.writeDeviceLunSize},
90fb299fa2Sopenharmony_ci        {DEFAULT_LUN_NUM_LABEL, &ptableData_.defaultLunNum},
91fb299fa2Sopenharmony_ci    };
92fb299fa2Sopenharmony_ci
93fb299fa2Sopenharmony_ci    for (auto dataVar : ptableDataVars) {
94fb299fa2Sopenharmony_ci        auto dataValue = ptableDataNode[dataVar.first.c_str()].As<uint32_t>();
95fb299fa2Sopenharmony_ci        if (!dataValue) {
96fb299fa2Sopenharmony_ci            LOG(ERROR) << "parse json failed! " << dataVar.first << " is nullptr!";
97fb299fa2Sopenharmony_ci            return false;
98fb299fa2Sopenharmony_ci        }
99fb299fa2Sopenharmony_ci        *(dataVar.second) = *dataValue;
100fb299fa2Sopenharmony_ci        LOG(INFO) << "set " << dataVar.first << " : " << *dataValue;
101fb299fa2Sopenharmony_ci    }
102fb299fa2Sopenharmony_ci    return true;
103fb299fa2Sopenharmony_ci}
104fb299fa2Sopenharmony_ci
105fb299fa2Sopenharmony_cibool Ptable::ParsePtableData()
106fb299fa2Sopenharmony_ci{
107fb299fa2Sopenharmony_ci    (void)memset_s(&ptableData_, sizeof(ptableData_), 0, sizeof(ptableData_));
108fb299fa2Sopenharmony_ci    std::ifstream ifs(std::string {PTABLE_CONFIG_PATH});
109fb299fa2Sopenharmony_ci    if (!ifs.is_open()) {
110fb299fa2Sopenharmony_ci        LOG(ERROR) << PTABLE_CONFIG_PATH << " not exist";
111fb299fa2Sopenharmony_ci        return false;
112fb299fa2Sopenharmony_ci    }
113fb299fa2Sopenharmony_ci
114fb299fa2Sopenharmony_ci    // get root node
115fb299fa2Sopenharmony_ci    std::string content {std::istreambuf_iterator<char> {ifs}, {}};
116fb299fa2Sopenharmony_ci    cJSONPtr root(cJSON_Parse(content.c_str()), cJSON_Delete);
117fb299fa2Sopenharmony_ci    if (root == nullptr) {
118fb299fa2Sopenharmony_ci        LOG(ERROR) << PTABLE_CONFIG_PATH << " contained json invalid";
119fb299fa2Sopenharmony_ci        return false;
120fb299fa2Sopenharmony_ci    }
121fb299fa2Sopenharmony_ci
122fb299fa2Sopenharmony_ci    JsonNode node(root.get(), false);
123fb299fa2Sopenharmony_ci    const JsonNode &ptableDataNode = node[PTABLE_DATA_LABEL];
124fb299fa2Sopenharmony_ci    bool ret = ParsePtableDataNode(ptableDataNode);
125fb299fa2Sopenharmony_ci    ptableData_.dataValid = ret;
126fb299fa2Sopenharmony_ci    return ret;
127fb299fa2Sopenharmony_ci}
128fb299fa2Sopenharmony_ci
129fb299fa2Sopenharmony_ciuint32_t Ptable::GetDefaultImageSize() const
130fb299fa2Sopenharmony_ci{
131fb299fa2Sopenharmony_ci    return ptableData_.emmcGptDataLen + ptableData_.defaultLunNum * ptableData_.imgLuSize;
132fb299fa2Sopenharmony_ci}
133fb299fa2Sopenharmony_ci
134fb299fa2Sopenharmony_cibool Ptable::CheckFileExist(const std::string &fileName)
135fb299fa2Sopenharmony_ci{
136fb299fa2Sopenharmony_ci    struct stat buffers;
137fb299fa2Sopenharmony_ci    if (memset_s(&buffers, sizeof(buffers), 0, sizeof(buffers)) != EOK) {
138fb299fa2Sopenharmony_ci        LOG(WARNING) << "memset_s fail";
139fb299fa2Sopenharmony_ci    }
140fb299fa2Sopenharmony_ci    if (stat(fileName.c_str(), &buffers) == 0) {
141fb299fa2Sopenharmony_ci        LOG(INFO) << fileName << " is exist";
142fb299fa2Sopenharmony_ci        return true;
143fb299fa2Sopenharmony_ci    }
144fb299fa2Sopenharmony_ci    LOG(INFO) << fileName << " is not exist";
145fb299fa2Sopenharmony_ci    return false;
146fb299fa2Sopenharmony_ci}
147fb299fa2Sopenharmony_ci
148fb299fa2Sopenharmony_cibool Ptable::MemReadWithOffset(const std::string &filePath, const uint64_t offset,
149fb299fa2Sopenharmony_ci    uint8_t *outData, const uint32_t dataSize)
150fb299fa2Sopenharmony_ci{
151fb299fa2Sopenharmony_ci    if (filePath.length() == 0 || outData == nullptr || dataSize == 0) {
152fb299fa2Sopenharmony_ci        LOG(ERROR) << "invaild input";
153fb299fa2Sopenharmony_ci        return false;
154fb299fa2Sopenharmony_ci    }
155fb299fa2Sopenharmony_ci
156fb299fa2Sopenharmony_ci    std::ifstream fin(filePath, std::ios::in);
157fb299fa2Sopenharmony_ci    if (fin.fail()) {
158fb299fa2Sopenharmony_ci        LOG(ERROR) << "open " << filePath << " fail";
159fb299fa2Sopenharmony_ci        return false;
160fb299fa2Sopenharmony_ci    }
161fb299fa2Sopenharmony_ci
162fb299fa2Sopenharmony_ci    fin.seekg(offset, std::ios::beg);
163fb299fa2Sopenharmony_ci    if (fin.tellg() != static_cast<long long>(offset)) {
164fb299fa2Sopenharmony_ci        LOG(ERROR) << "seekp 0x" << std::hex << offset << " bytes in " << filePath <<
165fb299fa2Sopenharmony_ci            " failed. Now is in 0x" << std::hex << fin.tellg() << std::dec;
166fb299fa2Sopenharmony_ci        fin.close();
167fb299fa2Sopenharmony_ci        return false;
168fb299fa2Sopenharmony_ci    }
169fb299fa2Sopenharmony_ci
170fb299fa2Sopenharmony_ci    if (!fin.read(reinterpret_cast<char *>(outData), dataSize)) {
171fb299fa2Sopenharmony_ci        LOG(ERROR) << "read 0x" << std::hex << dataSize << " bytes in " << filePath <<
172fb299fa2Sopenharmony_ci            " failed. only read 0x" << std::hex << fin.gcount() << std::dec;
173fb299fa2Sopenharmony_ci        fin.close();
174fb299fa2Sopenharmony_ci        return false;
175fb299fa2Sopenharmony_ci    }
176fb299fa2Sopenharmony_ci    fin.close();
177fb299fa2Sopenharmony_ci    return true;
178fb299fa2Sopenharmony_ci}
179fb299fa2Sopenharmony_ci
180fb299fa2Sopenharmony_ciuint32_t Ptable::Reflect(uint32_t data, const uint32_t len)
181fb299fa2Sopenharmony_ci{
182fb299fa2Sopenharmony_ci    uint32_t ref = 0;
183fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < len; i++) {
184fb299fa2Sopenharmony_ci        if (data & 0x1) {
185fb299fa2Sopenharmony_ci            ref |= (1 << ((len - 1) - i));
186fb299fa2Sopenharmony_ci        }
187fb299fa2Sopenharmony_ci        data = (data >> 1);
188fb299fa2Sopenharmony_ci    }
189fb299fa2Sopenharmony_ci    return ref;
190fb299fa2Sopenharmony_ci}
191fb299fa2Sopenharmony_ci
192fb299fa2Sopenharmony_ciuint32_t Ptable::CalculateCrc32(const uint8_t *buffer, const uint32_t len)
193fb299fa2Sopenharmony_ci{
194fb299fa2Sopenharmony_ci    if (buffer == nullptr || len == 0) {
195fb299fa2Sopenharmony_ci        LOG(INFO) << "invaild input";
196fb299fa2Sopenharmony_ci        return 0;
197fb299fa2Sopenharmony_ci    }
198fb299fa2Sopenharmony_ci    const uint32_t byteLen = 8; // 8:length of unit (i.e. byte)
199fb299fa2Sopenharmony_ci    uint32_t msb;
200fb299fa2Sopenharmony_ci    const uint64_t polynomial = 0x104C11DB7LL; // IEEE 32bit polynomial
201fb299fa2Sopenharmony_ci    uint32_t regs = 0xFFFFFFFF; // init to all ones
202fb299fa2Sopenharmony_ci    const uint32_t regsMask = 0xFFFFFFFF; // ensure only 32 bit answer
203fb299fa2Sopenharmony_ci    uint32_t regsMsb;
204fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < len; i++) {
205fb299fa2Sopenharmony_ci        uint32_t dataByte = buffer[i];
206fb299fa2Sopenharmony_ci        dataByte = Reflect(dataByte, 8); // 8:length of unit (i.e. byte)
207fb299fa2Sopenharmony_ci        for (uint32_t j = 0; j < byteLen; j++) {
208fb299fa2Sopenharmony_ci            msb = dataByte >> (byteLen - 1); // get MSB
209fb299fa2Sopenharmony_ci            msb &= 1; // ensure just 1 bit
210fb299fa2Sopenharmony_ci            regsMsb = (regs >> 31) & 1; // 31:32-1, MSB of regs
211fb299fa2Sopenharmony_ci            regs = regs << 1; // shift regs for CRC-CCITT
212fb299fa2Sopenharmony_ci            if (regsMsb ^ msb) { // MSB is a 1
213fb299fa2Sopenharmony_ci                regs = regs ^ polynomial; // XOR with generator poly
214fb299fa2Sopenharmony_ci            }
215fb299fa2Sopenharmony_ci            regs = regs & regsMask; // Mask off excess upper bits
216fb299fa2Sopenharmony_ci            dataByte <<= 1; // get to next bit
217fb299fa2Sopenharmony_ci        }
218fb299fa2Sopenharmony_ci    }
219fb299fa2Sopenharmony_ci    regs = regs & regsMask;
220fb299fa2Sopenharmony_ci    uint32_t ret = Reflect(regs, 32) ^ 0xFFFFFFFF; // 32:32bit
221fb299fa2Sopenharmony_ci    return ret;
222fb299fa2Sopenharmony_ci}
223fb299fa2Sopenharmony_ci
224fb299fa2Sopenharmony_cibool Ptable::VerifyMbrMagicNum(const uint8_t *buffer, const uint32_t size)
225fb299fa2Sopenharmony_ci{
226fb299fa2Sopenharmony_ci    // avoid checking past end of buffer
227fb299fa2Sopenharmony_ci    if (size < (MBR_MAGIC_NUM_POS + 1)) {
228fb299fa2Sopenharmony_ci        LOG(ERROR) << "size < (TABLE_SIGNATURE + 1)";
229fb299fa2Sopenharmony_ci        return false;
230fb299fa2Sopenharmony_ci    }
231fb299fa2Sopenharmony_ci    // check to see if magic number(0x55AA) exists at pos 0x1FE
232fb299fa2Sopenharmony_ci    if ((buffer[MBR_MAGIC_NUM_POS] != MBR_MAGIC_NUM_0) ||
233fb299fa2Sopenharmony_ci        (buffer[MBR_MAGIC_NUM_POS + 1] != MBR_MAGIC_NUM_1)) {
234fb299fa2Sopenharmony_ci        LOG(ERROR) << "MBR magic number does not match, magic buffer is " << unsigned(*(buffer + MBR_MAGIC_NUM_POS));
235fb299fa2Sopenharmony_ci        return false;
236fb299fa2Sopenharmony_ci    }
237fb299fa2Sopenharmony_ci    return true;
238fb299fa2Sopenharmony_ci}
239fb299fa2Sopenharmony_ci
240fb299fa2Sopenharmony_cibool Ptable::CheckProtectiveMbr(const uint8_t *gptImage, const uint32_t imgLen)
241fb299fa2Sopenharmony_ci{
242fb299fa2Sopenharmony_ci    if (!VerifyMbrMagicNum(gptImage, imgLen)) {
243fb299fa2Sopenharmony_ci        LOG(ERROR) << "MBR magic number verify failed!";
244fb299fa2Sopenharmony_ci        return false;
245fb299fa2Sopenharmony_ci    }
246fb299fa2Sopenharmony_ci
247fb299fa2Sopenharmony_ci    // process each of the four partitions in the MBR, find a Protective MBR(0xEE)
248fb299fa2Sopenharmony_ci    uint32_t type;
249fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < MBR_GPT_MAX_NUM; i++) {
250fb299fa2Sopenharmony_ci        // type 0xEE indicates the protective MBR and GPT partitions exist
251fb299fa2Sopenharmony_ci        if (MBR_GPT_ENTRY + i * MBR_GPT_ENTRY_SIZE + GPT_TYPE_SIGN_OFFSET >= imgLen) {
252fb299fa2Sopenharmony_ci            LOG(INFO) << "not find Protective MBR(type: 0xEE) in this partition";
253fb299fa2Sopenharmony_ci            return false;
254fb299fa2Sopenharmony_ci        }
255fb299fa2Sopenharmony_ci        type = gptImage[MBR_GPT_ENTRY + i * MBR_GPT_ENTRY_SIZE + GPT_TYPE_SIGN_OFFSET];
256fb299fa2Sopenharmony_ci        if (type == MBR_PROTECTIVE_GPT_TYPE) {
257fb299fa2Sopenharmony_ci            LOG(INFO) << "type is MBR_PROTECTIVE_GPT_TYPE(0xEE), GPT partitions exist";
258fb299fa2Sopenharmony_ci            return true;
259fb299fa2Sopenharmony_ci        }
260fb299fa2Sopenharmony_ci        LOG(INFO) << "the " << i << " main GPT's type=0x" << std::hex << type << std::dec;
261fb299fa2Sopenharmony_ci    }
262fb299fa2Sopenharmony_ci    LOG(INFO) << "not find Protective MBR(type: 0xEE) in this partition";
263fb299fa2Sopenharmony_ci    return false;
264fb299fa2Sopenharmony_ci}
265fb299fa2Sopenharmony_ci
266fb299fa2Sopenharmony_cibool Ptable::CheckIfValidGpt(const uint8_t *gptImage, const uint32_t gptImageLen)
267fb299fa2Sopenharmony_ci{
268fb299fa2Sopenharmony_ci    // 8 is the length of EFI_MAGIC_NUMBER
269fb299fa2Sopenharmony_ci    if (gptImageLen < 8) {
270fb299fa2Sopenharmony_ci        LOG(ERROR) << "gptImageLen is less than 8.";
271fb299fa2Sopenharmony_ci        return false;
272fb299fa2Sopenharmony_ci    }
273fb299fa2Sopenharmony_ci    // get magic number
274fb299fa2Sopenharmony_ci    uint64_t gptMagic = GET_LLWORD_FROM_BYTE(gptImage);
275fb299fa2Sopenharmony_ci    if (gptMagic != EFI_MAGIC_NUMBER) {
276fb299fa2Sopenharmony_ci        LOG(ERROR) << "invaild partiton with gptMagic:0x" << std::hex << gptMagic << std::dec;
277fb299fa2Sopenharmony_ci        return false;
278fb299fa2Sopenharmony_ci    }
279fb299fa2Sopenharmony_ci    return true;
280fb299fa2Sopenharmony_ci}
281fb299fa2Sopenharmony_ci
282fb299fa2Sopenharmony_cibool Ptable::GetCapacity(const std::string &filePath, uint64_t &lunCapacity)
283fb299fa2Sopenharmony_ci{
284fb299fa2Sopenharmony_ci    if (filePath.empty()) {
285fb299fa2Sopenharmony_ci        LOG(ERROR) << "filePath is empty or lunCapacity is nullptr";
286fb299fa2Sopenharmony_ci        return false;
287fb299fa2Sopenharmony_ci    }
288fb299fa2Sopenharmony_ci    std::ifstream fin(filePath, std::ios::in);
289fb299fa2Sopenharmony_ci    if (!fin.is_open()) {
290fb299fa2Sopenharmony_ci        LOG(ERROR) << "open " << filePath << " fail";
291fb299fa2Sopenharmony_ci        return false;
292fb299fa2Sopenharmony_ci    }
293fb299fa2Sopenharmony_ci
294fb299fa2Sopenharmony_ci    uint64_t sector = 0;
295fb299fa2Sopenharmony_ci    fin >> sector;
296fb299fa2Sopenharmony_ci    if (sector == 0) {
297fb299fa2Sopenharmony_ci        LOG(ERROR) << "read data from " << filePath << " fail";
298fb299fa2Sopenharmony_ci        fin.close();
299fb299fa2Sopenharmony_ci        return false;
300fb299fa2Sopenharmony_ci    }
301fb299fa2Sopenharmony_ci
302fb299fa2Sopenharmony_ci    uint64_t capacity = sector * SECTOR_SIZE;
303fb299fa2Sopenharmony_ci    LOG(INFO) << "lun capacity = 0x" << std::hex << capacity << std::dec;
304fb299fa2Sopenharmony_ci    lunCapacity = capacity;
305fb299fa2Sopenharmony_ci    fin.close();
306fb299fa2Sopenharmony_ci    return true;
307fb299fa2Sopenharmony_ci}
308fb299fa2Sopenharmony_ci
309fb299fa2Sopenharmony_cibool Ptable::GetPartitionGptHeaderInfo(const uint8_t *buffer, const uint32_t bufferLen, GPTHeaderInfo& gptHeaderInfo)
310fb299fa2Sopenharmony_ci{
311fb299fa2Sopenharmony_ci    if (buffer == nullptr || bufferLen < LBA_LENGTH) {
312fb299fa2Sopenharmony_ci        LOG(ERROR) << "input invalid";
313fb299fa2Sopenharmony_ci        return false;
314fb299fa2Sopenharmony_ci    }
315fb299fa2Sopenharmony_ci
316fb299fa2Sopenharmony_ci    // Check GPT Signature
317fb299fa2Sopenharmony_ci    if (!CheckIfValidGpt(buffer, bufferLen)) {
318fb299fa2Sopenharmony_ci        LOG(ERROR) << "invaild partiton with gptMagic";
319fb299fa2Sopenharmony_ci        return false;
320fb299fa2Sopenharmony_ci    }
321fb299fa2Sopenharmony_ci    gptHeaderInfo.headerSize = GET_LWORD_FROM_BYTE(buffer + HEADER_SIZE_OFFSET);
322fb299fa2Sopenharmony_ci    gptHeaderInfo.firstUsableLba = GET_LLWORD_FROM_BYTE(buffer + FIRST_USABLE_LBA_OFFSET);
323fb299fa2Sopenharmony_ci    gptHeaderInfo.maxPartitionCount = GET_LWORD_FROM_BYTE(buffer + PARTITION_COUNT_OFFSET);
324fb299fa2Sopenharmony_ci    gptHeaderInfo.partitionEntrySize = GET_LWORD_FROM_BYTE(buffer + PENTRY_SIZE_OFFSET);
325fb299fa2Sopenharmony_ci    if (gptHeaderInfo.maxPartitionCount == 0 || gptHeaderInfo.partitionEntrySize == 0) {
326fb299fa2Sopenharmony_ci        LOG(ERROR) << "invalid gpt header info";
327fb299fa2Sopenharmony_ci        return false;
328fb299fa2Sopenharmony_ci    }
329fb299fa2Sopenharmony_ci    return true;
330fb299fa2Sopenharmony_ci}
331fb299fa2Sopenharmony_ci
332fb299fa2Sopenharmony_civoid Ptable::PatchBackUpGptHeader(uint8_t *gptHeader, const uint32_t len, uint64_t backGptEntryStart)
333fb299fa2Sopenharmony_ci{
334fb299fa2Sopenharmony_ci    if (std::max({GPT_HEADER_OFFSET, BACKUP_HEADER_OFFSET, PARTITION_ENTRY_OFFSET}) + sizeof(uint64_t) > len ||
335fb299fa2Sopenharmony_ci        HEADER_CRC_OFFSET + sizeof(uint32_t) > len) {
336fb299fa2Sopenharmony_ci        LOG(ERROR) << "input param invalid";
337fb299fa2Sopenharmony_ci        return;
338fb299fa2Sopenharmony_ci    }
339fb299fa2Sopenharmony_ci    uint64_t gptHeaderOffset = GET_LLWORD_FROM_BYTE(gptHeader + GPT_HEADER_OFFSET);
340fb299fa2Sopenharmony_ci    uint64_t backHeaderOffset = GET_LLWORD_FROM_BYTE(gptHeader + BACKUP_HEADER_OFFSET);
341fb299fa2Sopenharmony_ci    PUT_LONG_LONG(gptHeader + GPT_HEADER_OFFSET, backHeaderOffset);
342fb299fa2Sopenharmony_ci    PUT_LONG_LONG(gptHeader + BACKUP_HEADER_OFFSET, gptHeaderOffset);
343fb299fa2Sopenharmony_ci    PUT_LONG_LONG(gptHeader + PARTITION_ENTRY_OFFSET, backGptEntryStart);
344fb299fa2Sopenharmony_ci    PUT_LONG(gptHeader + HEADER_CRC_OFFSET, 0);
345fb299fa2Sopenharmony_ci    uint32_t crcValue = CalculateCrc32(gptHeader, GPT_CRC_LEN);
346fb299fa2Sopenharmony_ci    PUT_LONG(gptHeader + HEADER_CRC_OFFSET, crcValue);
347fb299fa2Sopenharmony_ci    LOG(INFO) << "gpt header offset " << gptHeaderOffset << ", back header offset " << backHeaderOffset <<
348fb299fa2Sopenharmony_ci        ", crc value " << crcValue;
349fb299fa2Sopenharmony_ci}
350fb299fa2Sopenharmony_ci
351fb299fa2Sopenharmony_cibool Ptable::CheckGptHeader(uint8_t *buffer, const uint32_t bufferLen, const uint64_t lbaNum,
352fb299fa2Sopenharmony_ci    const GPTHeaderInfo& gptHeaderInfo)
353fb299fa2Sopenharmony_ci{
354fb299fa2Sopenharmony_ci    if (bufferLen < LBA_LENGTH || lbaNum == 0) {
355fb299fa2Sopenharmony_ci        LOG(ERROR) << "bufferLen < LBA_LENGTH || lbaNum == 0";
356fb299fa2Sopenharmony_ci        return false;
357fb299fa2Sopenharmony_ci    }
358fb299fa2Sopenharmony_ci
359fb299fa2Sopenharmony_ci    if (gptHeaderInfo.headerSize < GPT_HEADER_SIZE || gptHeaderInfo.headerSize > bufferLen) {
360fb299fa2Sopenharmony_ci        LOG(ERROR) << "GPT Header size is invaild";
361fb299fa2Sopenharmony_ci        return false;
362fb299fa2Sopenharmony_ci    }
363fb299fa2Sopenharmony_ci    uint32_t orgCrcVal = GET_LWORD_FROM_BYTE(buffer + HEADER_CRC_OFFSET);
364fb299fa2Sopenharmony_ci    // Write CRC field to 0 before calculating the crc of the whole rest of GPT header
365fb299fa2Sopenharmony_ci    PUT_LONG(buffer + HEADER_CRC_OFFSET, 0);
366fb299fa2Sopenharmony_ci    uint32_t crcVal = CalculateCrc32(buffer, gptHeaderInfo.headerSize);
367fb299fa2Sopenharmony_ci    if (crcVal != orgCrcVal) {
368fb299fa2Sopenharmony_ci        LOG(ERROR) << "Header crc mismatch crcVal = " << std::hex << crcVal << " with orgCrcVal = " <<
369fb299fa2Sopenharmony_ci            orgCrcVal << std::dec;
370fb299fa2Sopenharmony_ci        return false;
371fb299fa2Sopenharmony_ci    }
372fb299fa2Sopenharmony_ci    PUT_LONG(buffer + HEADER_CRC_OFFSET, crcVal);
373fb299fa2Sopenharmony_ci
374fb299fa2Sopenharmony_ci    uint32_t currentLba = GET_LLWORD_FROM_BYTE(buffer + PRIMARY_HEADER_OFFSET);
375fb299fa2Sopenharmony_ci    uint32_t lastUsableLba = GET_LLWORD_FROM_BYTE(buffer + LAST_USABLE_LBA_OFFSET);
376fb299fa2Sopenharmony_ci    uint32_t partition0 = GET_LLWORD_FROM_BYTE(buffer + PARTITION_ENTRIES_OFFSET);
377fb299fa2Sopenharmony_ci
378fb299fa2Sopenharmony_ci    // check for first and last lba range
379fb299fa2Sopenharmony_ci    if (gptHeaderInfo.firstUsableLba > lbaNum || lastUsableLba > lbaNum) {
380fb299fa2Sopenharmony_ci        LOG(ERROR) << "invalid usable lba " << gptHeaderInfo.firstUsableLba << ", last is " << lastUsableLba <<
381fb299fa2Sopenharmony_ci            " lbaNum is " << lbaNum;
382fb299fa2Sopenharmony_ci        return false;
383fb299fa2Sopenharmony_ci    }
384fb299fa2Sopenharmony_ci    // check for partition entry size
385fb299fa2Sopenharmony_ci    if (gptHeaderInfo.partitionEntrySize != PARTITION_ENTRY_SIZE ||
386fb299fa2Sopenharmony_ci        gptHeaderInfo.maxPartitionCount > (MIN_PARTITION_ARRAY_SIZE / PARTITION_ENTRY_SIZE)) {
387fb299fa2Sopenharmony_ci        LOG(ERROR) << "invalid parition entry size or max count";
388fb299fa2Sopenharmony_ci        return false;
389fb299fa2Sopenharmony_ci    }
390fb299fa2Sopenharmony_ci    // GPT header should always be the 0x1 LBA, partition entry should always the 0x2 LBA
391fb299fa2Sopenharmony_ci    if (currentLba != 0x1 || partition0 != 0x2) {
392fb299fa2Sopenharmony_ci        LOG(ERROR) << "starting LBA mismatch";
393fb299fa2Sopenharmony_ci        return false;
394fb299fa2Sopenharmony_ci    }
395fb299fa2Sopenharmony_ci    LOG(INFO) << "gpt header check ok";
396fb299fa2Sopenharmony_ci    return true;
397fb299fa2Sopenharmony_ci}
398fb299fa2Sopenharmony_ci
399fb299fa2Sopenharmony_cibool Ptable::PartitionCheckGptHeader(const uint8_t *gptImage, const uint32_t len, const uint64_t lbaNum,
400fb299fa2Sopenharmony_ci    const uint32_t blockSize, GPTHeaderInfo& gptHeaderInfo)
401fb299fa2Sopenharmony_ci{
402fb299fa2Sopenharmony_ci    if (len < ptableData_.writeDeviceLunSize || lbaNum == 0) {
403fb299fa2Sopenharmony_ci        LOG(ERROR) << "len" << len << "ptableData_.writeDeviceLunSize" << ptableData_.writeDeviceLunSize
404fb299fa2Sopenharmony_ci          << "lbaNum" << lbaNum;
405fb299fa2Sopenharmony_ci        return false;
406fb299fa2Sopenharmony_ci    }
407fb299fa2Sopenharmony_ci
408fb299fa2Sopenharmony_ci    uint8_t *buffer = new(std::nothrow) uint8_t[blockSize]();
409fb299fa2Sopenharmony_ci    if (buffer == nullptr) {
410fb299fa2Sopenharmony_ci        LOG(ERROR) << "new buffer failed!";
411fb299fa2Sopenharmony_ci        return false;
412fb299fa2Sopenharmony_ci    }
413fb299fa2Sopenharmony_ci    if (memcpy_s(buffer, blockSize, gptImage + blockSize, blockSize) != EOK) {
414fb299fa2Sopenharmony_ci        LOG(ERROR) << "copy gpt header fail";
415fb299fa2Sopenharmony_ci        delete [] buffer;
416fb299fa2Sopenharmony_ci        return false;
417fb299fa2Sopenharmony_ci    }
418fb299fa2Sopenharmony_ci
419fb299fa2Sopenharmony_ci    if (!CheckGptHeader(buffer, blockSize, lbaNum, gptHeaderInfo)) {
420fb299fa2Sopenharmony_ci        LOG(ERROR) << "CheckGptHeader fail";
421fb299fa2Sopenharmony_ci        delete [] buffer;
422fb299fa2Sopenharmony_ci        return false;
423fb299fa2Sopenharmony_ci    }
424fb299fa2Sopenharmony_ci
425fb299fa2Sopenharmony_ci    uint32_t partition0 = GET_LLWORD_FROM_BYTE(&buffer[PARTITION_ENTRIES_OFFSET]);
426fb299fa2Sopenharmony_ci    uint32_t orgCrcVal = GET_LWORD_FROM_BYTE(&buffer[PARTITION_CRC_OFFSET]);
427fb299fa2Sopenharmony_ci    delete [] buffer;
428fb299fa2Sopenharmony_ci
429fb299fa2Sopenharmony_ci    uint32_t crcVal = CalculateCrc32(gptImage + partition0 * blockSize,
430fb299fa2Sopenharmony_ci        gptHeaderInfo.maxPartitionCount * gptHeaderInfo.partitionEntrySize);
431fb299fa2Sopenharmony_ci    if (crcVal != orgCrcVal) {
432fb299fa2Sopenharmony_ci        LOG(ERROR) << "partition entires crc mismatch crcVal =" << std::hex << crcVal << " with orgCrcVal =" <<
433fb299fa2Sopenharmony_ci            orgCrcVal << std::dec;
434fb299fa2Sopenharmony_ci        return false;
435fb299fa2Sopenharmony_ci    }
436fb299fa2Sopenharmony_ci    LOG(INFO) << "PartitionCheckGptHeader ok";
437fb299fa2Sopenharmony_ci    return true;
438fb299fa2Sopenharmony_ci}
439fb299fa2Sopenharmony_ci
440fb299fa2Sopenharmony_civoid Ptable::PrintPtableInfo() const
441fb299fa2Sopenharmony_ci{
442fb299fa2Sopenharmony_ci    if (partitionInfo_.empty()) {
443fb299fa2Sopenharmony_ci        LOG(ERROR) << "ptable vector is empty!";
444fb299fa2Sopenharmony_ci        return;
445fb299fa2Sopenharmony_ci    }
446fb299fa2Sopenharmony_ci
447fb299fa2Sopenharmony_ci    LOG(INFO) << "ptnInfo : ===========================================";
448fb299fa2Sopenharmony_ci    LOG(INFO) << "partition count = " << std::dec << partitionInfo_.size();
449fb299fa2Sopenharmony_ci    for (size_t i = 0; i < partitionInfo_.size(); i++) {
450fb299fa2Sopenharmony_ci        LOG(INFO) << "ptable.entry[" << i << "].name=" << partitionInfo_[i].dispName.c_str() <<
451fb299fa2Sopenharmony_ci            ", startAddr=0x" << std::hex << partitionInfo_[i].startAddr << ", size=0x" <<
452fb299fa2Sopenharmony_ci            partitionInfo_[i].partitionSize << ", lun=" << std::dec << partitionInfo_[i].lun;
453fb299fa2Sopenharmony_ci    }
454fb299fa2Sopenharmony_ci    LOG(INFO) << "ptnInfo : ===========================================";
455fb299fa2Sopenharmony_ci}
456fb299fa2Sopenharmony_ci
457fb299fa2Sopenharmony_civoid Ptable::PrintPtableInfo(const std::vector<PtnInfo> &ptnInfo) const
458fb299fa2Sopenharmony_ci{
459fb299fa2Sopenharmony_ci    if (ptnInfo.empty()) {
460fb299fa2Sopenharmony_ci        LOG(ERROR) << "ptable vector is empty!";
461fb299fa2Sopenharmony_ci        return;
462fb299fa2Sopenharmony_ci    }
463fb299fa2Sopenharmony_ci
464fb299fa2Sopenharmony_ci    LOG(INFO) << "ptnInfo : ===========================================";
465fb299fa2Sopenharmony_ci    LOG(INFO) << "partition count = " << std::dec << ptnInfo.size();
466fb299fa2Sopenharmony_ci    for (size_t i = 0; i < ptnInfo.size(); i++) {
467fb299fa2Sopenharmony_ci        LOG(INFO) << "ptable.entry[" << i << "].name=" << ptnInfo[i].dispName.c_str() << ", startAddr=0x" <<
468fb299fa2Sopenharmony_ci        std::hex << ptnInfo[i].startAddr << ", size=0x" << ptnInfo[i].partitionSize << ", lun=" <<
469fb299fa2Sopenharmony_ci        std::dec << ptnInfo[i].lun;
470fb299fa2Sopenharmony_ci    }
471fb299fa2Sopenharmony_ci    LOG(INFO) << "ptnInfo : ===========================================";
472fb299fa2Sopenharmony_ci}
473fb299fa2Sopenharmony_ci
474fb299fa2Sopenharmony_civoid Ptable::ParsePartitionName(const uint8_t *data, const uint32_t dataLen,
475fb299fa2Sopenharmony_ci    std::string &name, const uint32_t nameLen)
476fb299fa2Sopenharmony_ci{
477fb299fa2Sopenharmony_ci    if (data == nullptr || dataLen == 0 || nameLen == 0) {
478fb299fa2Sopenharmony_ci        LOG(ERROR) << "dataLen == 0 || nameLen == 0";
479fb299fa2Sopenharmony_ci        return;
480fb299fa2Sopenharmony_ci    }
481fb299fa2Sopenharmony_ci    char utf16Name[MAX_GPT_NAME_SIZE] = {0};
482fb299fa2Sopenharmony_ci    if (memcpy_s(utf16Name, sizeof(utf16Name), data, dataLen) != EOK) {
483fb299fa2Sopenharmony_ci        LOG(ERROR) << "memcpy name fail";
484fb299fa2Sopenharmony_ci        return;
485fb299fa2Sopenharmony_ci    }
486fb299fa2Sopenharmony_ci
487fb299fa2Sopenharmony_ci    std::string outName;
488fb299fa2Sopenharmony_ci    // convert utf8 to utf16, 2 bytes for 1 charactor of partition name
489fb299fa2Sopenharmony_ci    for (uint32_t n = 0; n < nameLen && n < (MAX_GPT_NAME_SIZE / 2) && utf16Name[n * 2] != '\0'; n++) {
490fb299fa2Sopenharmony_ci        outName = outName + utf16Name[n * 2];
491fb299fa2Sopenharmony_ci    }
492fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < outName.size(); i++) {
493fb299fa2Sopenharmony_ci        outName[i] = static_cast<char>(toupper(outName[i]));
494fb299fa2Sopenharmony_ci    }
495fb299fa2Sopenharmony_ci    name = outName;
496fb299fa2Sopenharmony_ci    return;
497fb299fa2Sopenharmony_ci}
498fb299fa2Sopenharmony_ci
499fb299fa2Sopenharmony_cibool Ptable::WriteBufferToPath(const std::string &path, const uint64_t offset,
500fb299fa2Sopenharmony_ci    const uint8_t *buffer, const uint32_t size)
501fb299fa2Sopenharmony_ci{
502fb299fa2Sopenharmony_ci    std::unique_ptr<DataWriter> writer = DataWriter::CreateDataWriter(WRITE_RAW, path, offset);
503fb299fa2Sopenharmony_ci    if (writer == nullptr) {
504fb299fa2Sopenharmony_ci        LOG(ERROR) << "create writer class failed!";
505fb299fa2Sopenharmony_ci        return false;
506fb299fa2Sopenharmony_ci    }
507fb299fa2Sopenharmony_ci    bool ret = writer->Write(buffer, size, nullptr);
508fb299fa2Sopenharmony_ci    if (!ret) {
509fb299fa2Sopenharmony_ci        LOG(ERROR) << "writer to " << path << " with offset " << offset << " failed ";
510fb299fa2Sopenharmony_ci        DataWriter::ReleaseDataWriter(writer);
511fb299fa2Sopenharmony_ci        return false;
512fb299fa2Sopenharmony_ci    }
513fb299fa2Sopenharmony_ci    DataWriter::ReleaseDataWriter(writer);
514fb299fa2Sopenharmony_ci    return true;
515fb299fa2Sopenharmony_ci}
516fb299fa2Sopenharmony_ci
517fb299fa2Sopenharmony_cibool Ptable::GetPartionInfoByName(const std::string &partitionName, PtnInfo &ptnInfo, int32_t &index)
518fb299fa2Sopenharmony_ci{
519fb299fa2Sopenharmony_ci    if (partitionInfo_.empty()) {
520fb299fa2Sopenharmony_ci        LOG(ERROR) << "get partition failed! partitionInfo_ is empty";
521fb299fa2Sopenharmony_ci        return false;
522fb299fa2Sopenharmony_ci    }
523fb299fa2Sopenharmony_ci    for (int32_t i = 0; i < static_cast<int32_t>(partitionInfo_.size()); i++) {
524fb299fa2Sopenharmony_ci        if (partitionInfo_[i].dispName.size() == partitionName.size() &&
525fb299fa2Sopenharmony_ci            strcasecmp(partitionInfo_[i].dispName.c_str(), partitionName.c_str()) == 0) {
526fb299fa2Sopenharmony_ci            index = i;
527fb299fa2Sopenharmony_ci            ptnInfo = partitionInfo_[i];
528fb299fa2Sopenharmony_ci            return true;
529fb299fa2Sopenharmony_ci        }
530fb299fa2Sopenharmony_ci    }
531fb299fa2Sopenharmony_ci    LOG(ERROR) << "get partition info failed! Not found partition:" << partitionName;
532fb299fa2Sopenharmony_ci    return false;
533fb299fa2Sopenharmony_ci}
534fb299fa2Sopenharmony_ci
535fb299fa2Sopenharmony_cibool Ptable::AdjustGpt(uint8_t *ptnInfoBuf, uint64_t bufSize, const std::string &ptnName, uint64_t preLastLBA,
536fb299fa2Sopenharmony_ci    uint64_t lastPtnLastLBA)
537fb299fa2Sopenharmony_ci{
538fb299fa2Sopenharmony_ci    if (ptnInfoBuf == nullptr || bufSize == 0 || ptnName.empty()) {
539fb299fa2Sopenharmony_ci        LOG(ERROR) << "invalid input";
540fb299fa2Sopenharmony_ci        return false;
541fb299fa2Sopenharmony_ci    }
542fb299fa2Sopenharmony_ci    if (ptnName != LAST_PATITION_NAME) {
543fb299fa2Sopenharmony_ci        uint64_t firstLBA = GET_LLWORD_FROM_BYTE(&ptnInfoBuf[FIRST_LBA_OFFSET]);
544fb299fa2Sopenharmony_ci        uint64_t lastLBA = GET_LLWORD_FROM_BYTE(&ptnInfoBuf[LAST_LBA_OFFSET]);
545fb299fa2Sopenharmony_ci        lastLBA = lastLBA - firstLBA + preLastLBA + 1;
546fb299fa2Sopenharmony_ci        firstLBA = preLastLBA + 1;
547fb299fa2Sopenharmony_ci        PUT_LONG_LONG(ptnInfoBuf + FIRST_LBA_OFFSET, firstLBA);
548fb299fa2Sopenharmony_ci        PUT_LONG_LONG(ptnInfoBuf + LAST_LBA_OFFSET, lastLBA);
549fb299fa2Sopenharmony_ci    } else { /* this is USERDATA partition */
550fb299fa2Sopenharmony_ci        uint64_t firstLBA = preLastLBA + 1;
551fb299fa2Sopenharmony_ci        if (lastPtnLastLBA < firstLBA) {
552fb299fa2Sopenharmony_ci            LOG(ERROR) << "patch last partition fail";
553fb299fa2Sopenharmony_ci            return false;
554fb299fa2Sopenharmony_ci        }
555fb299fa2Sopenharmony_ci        PUT_LONG_LONG(ptnInfoBuf + FIRST_LBA_OFFSET, firstLBA);
556fb299fa2Sopenharmony_ci        /* resize last partition by device density */
557fb299fa2Sopenharmony_ci        PUT_LONG_LONG(ptnInfoBuf + LAST_LBA_OFFSET, lastPtnLastLBA);
558fb299fa2Sopenharmony_ci    }
559fb299fa2Sopenharmony_ci    return true;
560fb299fa2Sopenharmony_ci}
561fb299fa2Sopenharmony_ci
562fb299fa2Sopenharmony_cibool Ptable::ChangeGpt(uint8_t *gptBuf, uint64_t gptSize, GptParseInfo gptInfo, PtnInfo &modifyInfo)
563fb299fa2Sopenharmony_ci{
564fb299fa2Sopenharmony_ci    if (gptBuf == nullptr || gptSize == 0 || gptSize <= gptInfo.imgBlockSize || gptInfo.devBlockSize == 0) {
565fb299fa2Sopenharmony_ci        LOG(ERROR) << "input param invalid";
566fb299fa2Sopenharmony_ci        return false;
567fb299fa2Sopenharmony_ci    }
568fb299fa2Sopenharmony_ci    bool modifyDectect = false;
569fb299fa2Sopenharmony_ci    uint8_t *gptHead = gptBuf + gptInfo.imgBlockSize; // skip pmbr
570fb299fa2Sopenharmony_ci    uint32_t ptnEntrySize = GET_LLWORD_FROM_BYTE(&gptHead[PENTRY_SIZE_OFFSET]);
571fb299fa2Sopenharmony_ci    uint64_t ptnStart = GET_LLWORD_FROM_BYTE(&gptHead[PARTITION_ENTRIES_OFFSET]);
572fb299fa2Sopenharmony_ci    uint64_t readSize = ptnStart * gptInfo.imgBlockSize;
573fb299fa2Sopenharmony_ci    uint8_t *ptnInfoBuf = gptBuf + readSize;
574fb299fa2Sopenharmony_ci    uint64_t preLastLBA = 0;
575fb299fa2Sopenharmony_ci    uint64_t lastPtnLastLBA = gptInfo.devDensity / gptInfo.devBlockSize - 1;
576fb299fa2Sopenharmony_ci
577fb299fa2Sopenharmony_ci    while (readSize < gptSize) {
578fb299fa2Sopenharmony_ci        std::string dispName;
579fb299fa2Sopenharmony_ci        // convert utf8 to utf16, 2 bytes for 1 charactor of partition name
580fb299fa2Sopenharmony_ci        ParsePartitionName(&ptnInfoBuf[GPT_PARTITION_NAME_OFFSET], MAX_GPT_NAME_SIZE, dispName, MAX_GPT_NAME_SIZE / 2);
581fb299fa2Sopenharmony_ci        if (dispName.empty()) {
582fb299fa2Sopenharmony_ci            break;
583fb299fa2Sopenharmony_ci        }
584fb299fa2Sopenharmony_ci        if (modifyDectect) {
585fb299fa2Sopenharmony_ci            /* partition after modify part */
586fb299fa2Sopenharmony_ci            if (!AdjustGpt(ptnInfoBuf, gptSize - readSize, dispName, preLastLBA, lastPtnLastLBA)) {
587fb299fa2Sopenharmony_ci                return false;
588fb299fa2Sopenharmony_ci            }
589fb299fa2Sopenharmony_ci            preLastLBA = GET_LLWORD_FROM_BYTE(&ptnInfoBuf[LAST_LBA_OFFSET]);
590fb299fa2Sopenharmony_ci            ptnInfoBuf += ptnEntrySize;
591fb299fa2Sopenharmony_ci            readSize += static_cast<uint64_t>(ptnEntrySize);
592fb299fa2Sopenharmony_ci            continue;
593fb299fa2Sopenharmony_ci        }
594fb299fa2Sopenharmony_ci        if (dispName == modifyInfo.dispName) {
595fb299fa2Sopenharmony_ci            LOG(INFO) << "modify part dectected!! dispName = " << dispName;
596fb299fa2Sopenharmony_ci            uint64_t firstLBA = modifyInfo.startAddr / gptInfo.devBlockSize;
597fb299fa2Sopenharmony_ci            uint64_t lastLBA = firstLBA + modifyInfo.partitionSize / gptInfo.devBlockSize - 1;
598fb299fa2Sopenharmony_ci            if ((dispName == LAST_PATITION_NAME) && (lastLBA != lastPtnLastLBA)) {
599fb299fa2Sopenharmony_ci                return false;
600fb299fa2Sopenharmony_ci            }
601fb299fa2Sopenharmony_ci            PUT_LONG_LONG(ptnInfoBuf + FIRST_LBA_OFFSET, firstLBA);
602fb299fa2Sopenharmony_ci            PUT_LONG_LONG(ptnInfoBuf + LAST_LBA_OFFSET, lastLBA);
603fb299fa2Sopenharmony_ci            modifyDectect = true;
604fb299fa2Sopenharmony_ci            preLastLBA = lastLBA;
605fb299fa2Sopenharmony_ci        }
606fb299fa2Sopenharmony_ci        ptnInfoBuf += ptnEntrySize;
607fb299fa2Sopenharmony_ci        readSize += static_cast<uint64_t>(ptnEntrySize);
608fb299fa2Sopenharmony_ci    }
609fb299fa2Sopenharmony_ci    return true;
610fb299fa2Sopenharmony_ci}
611fb299fa2Sopenharmony_ci} // namespace Updater