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