• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "ufs_ptable.h"
17 
18 #include <algorithm>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include "log/log.h"
24 #include "securec.h"
25 #include "updater/updater_const.h"
26 
27 namespace Updater {
GetDeviceLunNum()28 uint32_t UfsPtable::GetDeviceLunNum()
29 {
30     return deviceLunNum_;
31 }
32 
GetDeviceLunCapacity(const uint32_t lunIndex)33 uint64_t UfsPtable::GetDeviceLunCapacity(const uint32_t lunIndex)
34 {
35     char lunIndexName = 'a' + lunIndex;
36     std::string capacityPath = std::string(PREFIX_SYS_CLASS_BLOCK) + lunIndexName + "/size";
37     uint64_t capacity = 0;
38     GetCapacity(capacityPath, capacity);
39     return capacity;
40 }
41 
SetDeviceLunNum()42 void UfsPtable::SetDeviceLunNum()
43 {
44     if (deviceLunNum_ > 0) {
45         return;
46     }
47     uint32_t lunIndex;
48     for (lunIndex = 0; lunIndex < MAX_LUN_NUMBERS; lunIndex++) {
49         char lunIndexName = 'a' + lunIndex;
50         std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
51         if (!CheckFileExist(ufsNode)) {
52             LOG(ERROR) << "file " << ufsNode << " is not exist";
53             break;
54         }
55     }
56     deviceLunNum_ = lunIndex;
57     return;
58 }
59 
ParseGptHeaderByUfsLun(const uint8_t * gptImage,const uint32_t len,const uint32_t lun,const uint32_t blockSize)60 bool UfsPtable::ParseGptHeaderByUfsLun(const uint8_t *gptImage, const uint32_t len,
61     const uint32_t lun, const uint32_t blockSize)
62 {
63     GPTHeaderInfo gptHeaderInfo;
64     (void)memset_s(&gptHeaderInfo, sizeof(GPTHeaderInfo), 0, sizeof(GPTHeaderInfo));
65     if (!GetPartitionGptHeaderInfo(gptImage + blockSize, blockSize, gptHeaderInfo)) {
66         LOG(ERROR) << "GetPartitionGptHeaderInfo fail";
67         return false;
68     }
69     uint64_t lunDeviceSize = GetDeviceLunCapacity(lun);
70     uint32_t lunLbaNum = lunDeviceSize / MIN_UFS_WRITE_SIZE;
71     return PartitionCheckGptHeader(gptImage, len, lunLbaNum, blockSize, gptHeaderInfo);
72 }
73 
UfsReadGpt(const uint8_t * gptImage,const uint32_t len,const uint32_t lun,const uint32_t blockSize)74 bool UfsPtable::UfsReadGpt(const uint8_t *gptImage, const uint32_t len,
75     const uint32_t lun, const uint32_t blockSize)
76 {
77     if (gptImage == nullptr || len < ptableData_.writeDeviceLunSize || lun >= MAX_LUN_NUMBERS || blockSize == 0) {
78         LOG(ERROR) << "invaild input";
79         return false;
80     }
81     if (!ParseGptHeaderByUfsLun(gptImage, len, lun, blockSize)) {
82         LOG(ERROR) << "Primary signature invalid";
83         return false;
84     }
85     auto startIter = partitionInfo_.end();
86     for (auto it = partitionInfo_.begin(); it != partitionInfo_.end();) {
87         if ((*it).lun == lun) {
88             it = partitionInfo_.erase(it);
89             startIter = it;
90             continue;
91         }
92         it++;
93     }
94 
95     uint32_t partEntryCnt = blockSize / PARTITION_ENTRY_SIZE;
96     uint32_t partition0 = GET_LLWORD_FROM_BYTE(gptImage + blockSize + PARTITION_ENTRIES_OFFSET);
97 
98     uint32_t count = 0;
99     const uint8_t *data = nullptr;
100     for (uint32_t i = 0; i < (MAX_PARTITION_NUM / partEntryCnt) && count < MAX_PARTITION_NUM; i++) {
101         data = gptImage + (partition0 + i) * blockSize;
102         for (uint32_t j = 0; j < partEntryCnt; j++) {
103             uint8_t typeGuid[GPT_PARTITION_TYPE_GUID_LEN] = {0};
104             if (memcpy_s(typeGuid, sizeof(typeGuid), &data[(j * PARTITION_ENTRY_SIZE)], sizeof(typeGuid)) != EOK) {
105                 LOG(ERROR) << "memcpy guid fail";
106             }
107             if (typeGuid[0] == 0x00 && typeGuid[1] == 0x00) { // 0x00 means no partition
108                 i = MAX_PARTITION_NUM / partEntryCnt;
109                 break;
110             }
111             uint64_t firstLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + FIRST_LBA_OFFSET]);
112             uint64_t lastLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + LAST_LBA_OFFSET]);
113             // add a new partition info into partitionInfo_ vector
114             PtnInfo newPtnInfo;
115             (void)memset_s(&newPtnInfo, sizeof(newPtnInfo), 0, sizeof(newPtnInfo));
116             newPtnInfo.startAddr = firstLba * static_cast<uint64_t>(MIN_UFS_WRITE_SIZE);
117             // General algorithm : calculate partition size by lba
118             newPtnInfo.partitionSize = (lastLba - firstLba + 1) * static_cast<uint64_t>(MIN_UFS_WRITE_SIZE);
119             const uint8_t *nameOffset = data + (j * PARTITION_ENTRY_SIZE + GPT_PARTITION_NAME_OFFSET);
120             // 2 bytes for 1 charactor of partition name
121             ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, newPtnInfo.dispName, MAX_GPT_NAME_SIZE / 2);
122             (void)memcpy_s(newPtnInfo.partitionTypeGuid, sizeof(newPtnInfo.partitionTypeGuid),
123                 typeGuid, sizeof(typeGuid));
124             newPtnInfo.lun = lun;
125             startIter = ++(partitionInfo_.insert(startIter, newPtnInfo));
126             count++;
127         }
128     }
129     return true;
130 }
131 
132 
UfsPatchGptHeader(UfsPartitionDataInfo & ptnDataInfo,const uint32_t blockSize)133 void UfsPtable::UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize)
134 {
135     // mbr len + gptHeader len = 2 blockSize
136     if (blockSize == 0 || ptnDataInfo.writeDataLen < 2 * blockSize || ptnDataInfo.lunSize == 0) {
137         LOG(ERROR) << "invaild argument";
138         return;
139     }
140     uint64_t cardSizeSector = ptnDataInfo.lunSize / MIN_UFS_WRITE_SIZE;
141     if (cardSizeSector == 0) {
142         cardSizeSector = DEFAULT_SECTOR_NUM;
143     }
144     // Patching primary header
145     uint8_t *primaryGptHeader = ptnDataInfo.data + blockSize;
146     PUT_LONG_LONG(primaryGptHeader + BACKUP_HEADER_OFFSET, (cardSizeSector - 1));
147     PUT_LONG_LONG(primaryGptHeader + LAST_USABLE_LBA_OFFSET, (cardSizeSector - 1));
148     // Find last partition
149     uint32_t totalPart = 0;
150     while (((TMP_DATA_SIZE - blockSize - blockSize) > totalPart * PARTITION_ENTRY_SIZE) &&
151         (*(primaryGptHeader + blockSize + totalPart * PARTITION_ENTRY_SIZE) != 0)) {
152         totalPart++;
153     }
154     if (totalPart == 0) {
155         LOG(ERROR) << "no partition exist";
156         return;
157     }
158     // Patching last partition
159     uint8_t *lastPartOffset = primaryGptHeader + blockSize + (totalPart - 1) * PARTITION_ENTRY_SIZE;
160     uint64_t lastLba = GET_LLWORD_FROM_BYTE(lastPartOffset + PARTITION_ENTRY_LAST_LBA);
161     uint64_t firstLba = GET_LLWORD_FROM_BYTE(lastPartOffset + FIRST_LBA_OFFSET);
162     // General algorithm : calculate partition size by lba
163     uint64_t partitionSize = (lastLba - firstLba + 1) * MIN_UFS_WRITE_SIZE;
164     std::string partitionName;
165     uint8_t *nameOffset = lastPartOffset + GPT_PARTITION_NAME_OFFSET;
166     // 2 bytes for 1 charactor of partition name
167     ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, partitionName, MAX_GPT_NAME_SIZE / 2);
168     if (partitionName == USERDATA_PARTITION || (totalPart == 1 && partitionSize == 0)) {
169         // patch userdata or only one partition
170         PUT_LONG_LONG(lastPartOffset + PARTITION_ENTRY_LAST_LBA, (cardSizeSector - 1));
171         LOG(INFO) << "partitionSize=" << partitionSize << ", partition_name:" << partitionName;
172     }
173 
174     // Updating CRC of the Partition entry array in both headers
175     uint32_t partCount = GET_LWORD_FROM_BYTE(primaryGptHeader + PARTITION_COUNT_OFFSET);
176     uint32_t entrySize = GET_LWORD_FROM_BYTE(primaryGptHeader + PENTRY_SIZE_OFFSET);
177     // mbr len + gptHeader len = 2 blockSize
178     uint32_t crcValue = CalculateCrc32(ptnDataInfo.data + (blockSize * 2), partCount * entrySize);
179     PUT_LONG(primaryGptHeader + PARTITION_CRC_OFFSET, crcValue);
180     // Clearing CRC fields to calculate
181     PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, 0);
182     crcValue = CalculateCrc32(primaryGptHeader, GPT_CRC_LEN);
183     PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, crcValue);
184     return;
185 }
186 
187 // blocksize is 4096, lbaLen is 512. Because in ptable.img block is 512 while in device block is 4096
ParsePartitionFromBuffer(uint8_t * ptbImgBuffer,const uint32_t imgBufSize)188 bool UfsPtable::ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize)
189 {
190     if (ptbImgBuffer == nullptr) {
191         LOG(ERROR) << "input param invalid";
192         return false;
193     }
194 
195     uint32_t imgBlockSize = ptableData_.lbaLen; // 512
196     uint32_t deviceBlockSize = ptableData_.blockSize; // 4096
197     if (imgBufSize < ptableData_.emmcGptDataLen + ptableData_.imgLuSize) {
198         LOG(ERROR) << "input param invalid imgBufSize";
199         return false;
200     }
201 
202     SetDeviceLunNum();
203     LOG(INFO) << "lun number of ptable:" << deviceLunNum_;
204 
205     for (uint32_t i = 0; i < deviceLunNum_; i++) {
206         UfsPartitionDataInfo newLunPtnDataInfo;
207         (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
208         uint8_t *lunStart = GetPtableImageUfsLunPmbrStart(ptbImgBuffer, i);
209         uint8_t *gptHeaderStart = GetPtableImageUfsLunGptHeaderStart(ptbImgBuffer, i);
210         // first block is mbr, second block is gptHeader
211         if (!CheckProtectiveMbr(lunStart, imgBlockSize) || !CheckIfValidGpt(gptHeaderStart, imgBlockSize)) {
212             newLunPtnDataInfo.isGptVaild = false;
213             ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
214             continue;
215         }
216         // for hisi: change ptable.img(512 bytes/block) into format of device(4096 bytes/block)
217         if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, lunStart, imgBlockSize) != EOK) {
218             LOG(WARNING) << "memcpy_s pmbr fail";
219         }
220         if (memcpy_s(newLunPtnDataInfo.data + deviceBlockSize, TMP_DATA_SIZE - deviceBlockSize,
221             gptHeaderStart, imgBlockSize) != EOK) {
222             LOG(WARNING) << "memcpy_s gpt header fail";
223         }
224         // skip 2 lba length to set gpt entry
225         if (memcpy_s(newLunPtnDataInfo.data + 2 * deviceBlockSize, TMP_DATA_SIZE - 2 * deviceBlockSize,
226             GetPtableImageUfsLunEntryStart(ptbImgBuffer, i), GPT_ENTRYS_SIZE) != EOK) {
227             LOG(WARNING) << "memcpy_s gpt data fail";
228         }
229         newLunPtnDataInfo.writeDataLen = ptableData_.writeDeviceLunSize;
230         newLunPtnDataInfo.lunIndex = i + ptableData_.startLunNumber;
231         newLunPtnDataInfo.lunSize = GetDeviceLunCapacity(newLunPtnDataInfo.lunIndex);
232         UfsPatchGptHeader(newLunPtnDataInfo, deviceBlockSize);
233         newLunPtnDataInfo.isGptVaild = true;
234         ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
235         if (!UfsReadGpt(newLunPtnDataInfo.data, newLunPtnDataInfo.writeDataLen,
236             newLunPtnDataInfo.lunIndex, deviceBlockSize)) {
237             LOG(ERROR) << "parse ufs gpt fail";
238             return false;
239         }
240     }
241     return true;
242 }
243 
ReadAndCheckMbr(const uint32_t lunIndex,const uint32_t blockSize)244 bool UfsPtable::ReadAndCheckMbr(const uint32_t lunIndex, const uint32_t blockSize)
245 {
246     if (blockSize <= 0 || lunIndex < 0 || lunIndex > deviceLunNum_) {
247         LOG(ERROR) << "blockSize <= 0";
248         return false;
249     }
250 
251     uint8_t *buffer = new(std::nothrow) uint8_t[blockSize]();
252     if (buffer == nullptr) {
253         LOG(ERROR) << "new buffer failed!";
254         return false;
255     }
256     char lunIndexName = 'a' + lunIndex;
257     std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
258     if (!MemReadWithOffset(ufsNode, 0, buffer, blockSize)) {
259         LOG(ERROR) << "read " << blockSize << " bytes from ufsNode " << ufsNode << " failed!";
260         delete [] buffer;
261         return false;
262     }
263 
264     bool result = CheckProtectiveMbr(buffer, blockSize);
265 
266     delete [] buffer;
267     return result;
268 }
269 
GetLunNumFromNode(const std::string & ufsNode)270 int32_t UfsPtable::GetLunNumFromNode(const std::string &ufsNode)
271 {
272     if (std::char_traits<char>::length(PREFIX_UFS_NODE) + 1 != ufsNode.length()) {
273         LOG(ERROR) << "ufsNode length is " << ufsNode.length() << ", \
274             not equal to PREFIX_UFS_NODE(" << std::char_traits<char>::length(PREFIX_UFS_NODE) << ") + 1";
275         return -1;
276     }
277     char ufsLunIndex = ufsNode.back();
278     // such as : 'a' - 'a'
279     return (ufsLunIndex - 'a');
280 }
281 
LoadPartitionInfoFromLun(const uint32_t lunIndex,const uint32_t imgLen)282 bool UfsPtable::LoadPartitionInfoFromLun(const uint32_t lunIndex, const uint32_t imgLen)
283 {
284     if (imgLen == 0 || lunIndex < 0 || lunIndex > deviceLunNum_) {
285         LOG(ERROR) << "imgLen or lunIndex is invaild";
286         return false;
287     }
288     char lunIndexName = 'a' + lunIndex;
289     std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
290 
291     uint8_t *buffer = new(std::nothrow) uint8_t[imgLen]();
292     if (buffer == nullptr) {
293         LOG(ERROR) << "new buffer failed!";
294         return false;
295     }
296     if (!MemReadWithOffset(ufsNode, 0, buffer, imgLen)) {
297         LOG(ERROR) << "read " << imgLen << " bytes from ufsNode " << ufsNode << " failed!";
298         delete [] buffer;
299         return false;
300     }
301     UfsPartitionDataInfo newLunPtnDataInfo;
302     newLunPtnDataInfo.isGptVaild = true;
303     newLunPtnDataInfo.lunIndex = lunIndex;
304     newLunPtnDataInfo.lunSize = imgLen;
305     newLunPtnDataInfo.writeDataLen = imgLen;
306     (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
307     if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, buffer, imgLen) != EOK) {
308         LOG(WARNING) << "memcpy_s mbr fail";
309     }
310 
311     ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
312     int32_t result = UfsReadGpt(buffer, imgLen, lunIndex, MIN_UFS_WRITE_SIZE);
313     delete [] buffer;
314     return result;
315 }
316 
LoadAllLunPartitions()317 uint32_t UfsPtable::LoadAllLunPartitions()
318 {
319     uint32_t lunIndex;
320     for (lunIndex = 0; lunIndex < deviceLunNum_; lunIndex++) {
321         if (ReadAndCheckMbr(lunIndex, MIN_UFS_WRITE_SIZE)) {
322             LoadPartitionInfoFromLun(lunIndex, ptableData_.writeDeviceLunSize);
323         }
324     }
325     return lunIndex;
326 }
327 
LoadPtableFromDevice()328 bool UfsPtable::LoadPtableFromDevice()
329 {
330     if (!partitionInfo_.empty()) {
331         LOG(INFO) << "ptable is already loaded to ram";
332         return true;
333     }
334     SetDeviceLunNum();
335     if (LoadAllLunPartitions() == 0) {
336         LOG(ERROR) << "init ptable to ram fail";
337         return false;
338     }
339     LOG(INFO) << "init ptable to ram ok";
340     return true;
341 }
342 
WritePartitionTable()343 bool UfsPtable::WritePartitionTable()
344 {
345     if (ufsPtnDataInfo_.empty()) {
346         LOG(ERROR) << "ufsPtnDataInfo_ is empty, write failed!";
347         return false;
348     }
349     for (uint32_t i = 0; i < ufsPtnDataInfo_.size(); i++) {
350         uint64_t writeDataLen = ufsPtnDataInfo_[i].writeDataLen;
351         char lunIndexName = 'a' + ufsPtnDataInfo_[i].lunIndex;
352         std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
353         LOG(INFO) << "ufs node name:" << ufsNode << ", writeDataLen = " << writeDataLen;
354 
355         if (!ufsPtnDataInfo_[i].isGptVaild) {
356             LOG(WARNING) <<  "invaild ptable, no need to update";
357             continue;
358         }
359         if (!WriteBufferToPath(ufsNode, 0, ufsPtnDataInfo_[i].data, writeDataLen)) {
360             LOG(ERROR) << "write first gpt fail";
361             return false;
362         }
363     }
364     return true;
365 }
366 
GetPtableImageUfsLunPmbrStart(uint8_t * imageBuf,const uint32_t lunIndex)367 uint8_t *UfsPtable::GetPtableImageUfsLunPmbrStart(uint8_t *imageBuf, const uint32_t lunIndex)
368 {
369     uint32_t pmbrStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize;
370     LOG(INFO) << "GetPtableImageUfsLunPmbrStart : " << std::hex << pmbrStart << std::dec;
371     return imageBuf + pmbrStart;
372 }
373 
GetPtableImageUfsLunGptHeaderStart(uint8_t * imageBuf,const uint32_t lunIndex)374 uint8_t *UfsPtable::GetPtableImageUfsLunGptHeaderStart(uint8_t *imageBuf, const uint32_t lunIndex)
375 {
376     uint32_t gptHeaderStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize + ptableData_.lbaLen;
377     LOG(INFO) << "GetPtableImageUfsLunGptHeaderStart : " << std::hex << gptHeaderStart << std::dec;
378     return imageBuf + gptHeaderStart;
379 }
380 
GetPtableImageUfsLunEntryStart(uint8_t * imageBuf,const uint32_t lunIndex)381 uint8_t *UfsPtable::GetPtableImageUfsLunEntryStart(uint8_t *imageBuf, const uint32_t lunIndex)
382 {
383     uint32_t entryStart = ptableData_.emmcGptDataLen + lunIndex * ptableData_.imgLuSize +
384         ptableData_.lbaLen + ptableData_.gptHeaderLen;
385     LOG(INFO) << "GetPtableImageUfsLunEntryStart : " << std::hex << entryStart << std::dec;
386     return imageBuf + entryStart;
387 }
388 
EditPartitionBuf(uint8_t * imageBuf,uint64_t imgBufSize,std::vector<PtnInfo> & modifyList)389 bool UfsPtable::EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector<PtnInfo> &modifyList)
390 {
391     if (imageBuf == nullptr || imgBufSize == 0 || modifyList.empty() || ptableData_.blockSize == 0) {
392         LOG(ERROR) << "input invalid";
393         return false;
394     }
395     if (imgBufSize < ptableData_.emmcGptDataLen || deviceLunNum_ == 0) {
396         LOG(ERROR) << "can not get offset, imgBufsize =" << imgBufSize << ",emmcGptDataLen ="
397             << ptableData_.emmcGptDataLen << ", deviceLunNum = " << deviceLunNum_;
398         return false;
399     }
400 
401     uint32_t gptSize = ptableData_.imgLuSize;
402     uint32_t imgBlockSize = ptableData_.lbaLen; // 512
403     uint32_t deviceBlockSize = ptableData_.blockSize; // 4096
404     uint32_t startLu = ptableData_.startLunNumber;
405     for (uint32_t i = 0; i < deviceLunNum_; ++i) {
406         char lunIndexName = 'a' + i + startLu;
407         UfsPartitionDataInfo newLunPtnDataInfo;
408         (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
409         std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
410         newLunPtnDataInfo.lunSize = GetDeviceLunCapacity(i + startLu);
411         if (newLunPtnDataInfo.lunSize == 0) {
412             LOG(ERROR) << "get devDenisity failed in " << ufsNode;
413             return false;
414         }
415         uint8_t *curGptBuf = GetPtableImageUfsLunPmbrStart(imageBuf, i + startLu);
416         if (!ufsPtnDataInfo_[i].isGptVaild) {
417             continue;
418         }
419         struct GptParseInfo gptInfo(imgBlockSize, deviceBlockSize, newLunPtnDataInfo.lunSize);
420         for (auto &t : modifyList) {
421             if (static_cast<uint32_t>(t.lun) == i + startLu && !ChangeGpt(curGptBuf, gptSize, gptInfo, t)) {
422                 LOG(ERROR) << "ChangeGpt failed";
423                 return false;
424             }
425         }
426         /* mbr block = 1 block */
427         if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, curGptBuf, imgBlockSize) != EOK) {
428             LOG(WARNING) << "memcpy_s fail";
429         }
430         newLunPtnDataInfo.writeDataLen = ptableData_.writeDeviceLunSize;
431         UfsPatchGptHeader(newLunPtnDataInfo, imgBlockSize);
432     }
433     return true;
434 }
435 
GetPtableImageBuffer(uint8_t * imageBuf,const uint32_t imgBufSize)436 bool UfsPtable::GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize)
437 {
438     uint32_t imgBlockSize = ptableData_.lbaLen; // 512
439     uint32_t deviceBlockSize = ptableData_.blockSize; // 4096
440     SetDeviceLunNum();
441     if (imageBuf == nullptr || imgBufSize == 0 ||
442         imgBufSize < ptableData_.emmcGptDataLen + ptableData_.imgLuSize * deviceLunNum_) {
443         LOG(ERROR) << "input param invalid";
444         return false;
445     }
446     for (uint32_t i = 0; i < deviceLunNum_; ++i) {
447         uint32_t curImgOffset = 0;
448         uint32_t curDevOffset = 0;
449         uint32_t imgOffset = ptableData_.emmcGptDataLen + ptableData_.imgLuSize * i;
450         /* get ufs node name */
451         char lunIndexName = 'a' + i + ptableData_.startLunNumber;
452         std::string ufsNode = std::string(PREFIX_UFS_NODE) + lunIndexName;
453         if (!CheckFileExist(ufsNode)) {
454             LOG(ERROR) << "file " << ufsNode << " is not exist";
455             return false;
456         }
457         /* get mbr head */
458         if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, imgBlockSize)) {
459             LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error";
460             return false;
461         }
462         bool isGptExist = CheckProtectiveMbr(imageBuf + curImgOffset + imgOffset, imgBlockSize);
463         curImgOffset += imgBlockSize;
464         curDevOffset += deviceBlockSize;
465         if (!isGptExist) {
466             continue;
467         }
468         /* get gpt head */
469         if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, imgBlockSize)) {
470             LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error";
471             return false;
472         }
473         uint32_t maxPartCount = GET_LWORD_FROM_BYTE(&imageBuf[imgOffset + curImgOffset + PARTITION_COUNT_OFFSET]);
474         uint32_t entrySize = GET_LWORD_FROM_BYTE(&imageBuf[imgOffset + curImgOffset + PENTRY_SIZE_OFFSET]);
475         curImgOffset += imgBlockSize;
476         curDevOffset += deviceBlockSize;
477         /* get gpt buf */
478         uint32_t gptInfoLen = maxPartCount * entrySize;
479         if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, gptInfoLen)) {
480             LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error" << gptInfoLen;
481             return false;
482         }
483     }
484     return true;
485 }
486 } // namespace Updater
487