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
GetPtableExtraOffset(void)42 uint32_t UfsPtable::GetPtableExtraOffset(void)
43 {
44 return 0;
45 }
46
47 // avoid u disk being recognized as a valid gpt lun device
CheckDeviceLunRemoveable(const uint32_t lunIndex)48 bool UfsPtable::CheckDeviceLunRemoveable(const uint32_t lunIndex)
49 {
50 constexpr uint32_t minRemoveableStartIdx = 3;
51 if (lunIndex <= minRemoveableStartIdx) {
52 return false;
53 }
54 char lunIndexName = 'a' + lunIndex;
55 std::string removableNode = std::string(PREFIX_SYS_CLASS_BLOCK) + lunIndexName + "/removable";
56 std::string removableResult {};
57 std::ifstream fin(removableNode, std::ios::in);
58 if (!fin.is_open()) {
59 LOG(ERROR) << "open " << removableNode << " failed";
60 return false;
61 }
62 fin >> removableResult;
63 LOG(INFO) << "lun " << lunIndex << " removable result is : " << removableResult;
64 return removableResult == "1";
65 }
66
GetDeviceBlockSize(void)67 uint32_t UfsPtable::GetDeviceBlockSize(void)
68 {
69 return ptableData_.blockSize;
70 }
71
GetDeviceLunNodePath(const uint32_t lun)72 std::string UfsPtable::GetDeviceLunNodePath(const uint32_t lun)
73 {
74 char lunIndexName = 'a' + lun;
75 return std::string(PREFIX_UFS_NODE) + lunIndexName;
76 }
77
SetDeviceLunNum()78 void UfsPtable::SetDeviceLunNum()
79 {
80 if (deviceLunNum_ > 0) {
81 return;
82 }
83 uint32_t lunIndex;
84 for (lunIndex = 0; lunIndex < MAX_LUN_NUMBERS; lunIndex++) {
85 std::string ufsNode = GetDeviceLunNodePath(lunIndex);
86 if (!CheckFileExist(ufsNode)) {
87 LOG(ERROR) << "file " << ufsNode << " is not exist";
88 break;
89 }
90 #ifndef UPDATER_UT
91 if (CheckDeviceLunRemoveable(lunIndex)) {
92 LOG(ERROR) << "device " << ufsNode << " is removable, may be a u disk";
93 break;
94 }
95 #endif
96 }
97 deviceLunNum_ = lunIndex;
98 LOG(INFO) << "device lun num is " << deviceLunNum_;
99 return;
100 }
101
ParseGptHeaderByUfsLun(const uint8_t * gptImage,const uint32_t len,const uint32_t lun,const uint32_t blockSize)102 bool UfsPtable::ParseGptHeaderByUfsLun(const uint8_t *gptImage, const uint32_t len,
103 const uint32_t lun, const uint32_t blockSize)
104 {
105 GPTHeaderInfo gptHeaderInfo;
106 (void)memset_s(&gptHeaderInfo, sizeof(GPTHeaderInfo), 0, sizeof(GPTHeaderInfo));
107 if (!GetPartitionGptHeaderInfo(gptImage + blockSize, blockSize, gptHeaderInfo)) {
108 LOG(ERROR) << "GetPartitionGptHeaderInfo fail";
109 return false;
110 }
111 uint32_t deviceBlockSize = GetDeviceBlockSize();
112 if (deviceBlockSize == 0) {
113 LOG(ERROR) << "block device size invalid " << deviceBlockSize;
114 return false;
115 }
116 uint64_t lunDeviceSize = GetDeviceLunCapacity(lun);
117 uint32_t lunLbaNum = lunDeviceSize / deviceBlockSize;
118 return PartitionCheckGptHeader(gptImage, len, lunLbaNum, blockSize, gptHeaderInfo);
119 }
120
UfsReadGpt(const uint8_t * gptImage,const uint32_t len,const uint32_t lun,const uint32_t blockSize)121 bool UfsPtable::UfsReadGpt(const uint8_t *gptImage, const uint32_t len,
122 const uint32_t lun, const uint32_t blockSize)
123 {
124 if (gptImage == nullptr || len < ptableData_.writeDeviceLunSize || lun >= MAX_LUN_NUMBERS || blockSize == 0) {
125 LOG(ERROR) << "invaild input";
126 return false;
127 }
128 if (!ParseGptHeaderByUfsLun(gptImage, len, lun, blockSize)) {
129 LOG(ERROR) << "Primary signature invalid";
130 return false;
131 }
132 auto startIter = partitionInfo_.end();
133 for (auto it = partitionInfo_.begin(); it != partitionInfo_.end();) {
134 if ((*it).lun == lun) {
135 it = partitionInfo_.erase(it);
136 startIter = it;
137 continue;
138 }
139 it++;
140 }
141
142 uint32_t partEntryCnt = blockSize / PARTITION_ENTRY_SIZE;
143 uint32_t partition0 = GET_LLWORD_FROM_BYTE(gptImage + blockSize + PARTITION_ENTRIES_OFFSET);
144
145 uint32_t count = 0;
146 const uint8_t *data = nullptr;
147 for (uint32_t i = 0; i < (MAX_PARTITION_NUM / partEntryCnt) && count < MAX_PARTITION_NUM; i++) {
148 data = gptImage + (partition0 + i) * blockSize;
149 for (uint32_t j = 0; j < partEntryCnt; j++) {
150 uint8_t typeGuid[GPT_PARTITION_TYPE_GUID_LEN] = {0};
151 if (memcpy_s(typeGuid, sizeof(typeGuid), &data[(j * PARTITION_ENTRY_SIZE)], sizeof(typeGuid)) != EOK) {
152 LOG(ERROR) << "memcpy guid fail";
153 }
154 if (typeGuid[0] == 0x00 && typeGuid[1] == 0x00) { // 0x00 means no partition
155 i = MAX_PARTITION_NUM / partEntryCnt;
156 break;
157 }
158 uint64_t firstLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + FIRST_LBA_OFFSET]);
159 uint64_t lastLba = GET_LLWORD_FROM_BYTE(&data[(j * PARTITION_ENTRY_SIZE) + LAST_LBA_OFFSET]);
160 // add a new partition info into partitionInfo_ vector
161 PtnInfo newPtnInfo = {};
162 newPtnInfo.startAddr = firstLba * static_cast<uint64_t>(GetDeviceBlockSize());
163 newPtnInfo.writePath = GetDeviceLunNodePath(lun);
164 // General algorithm : calculate partition size by lba
165 newPtnInfo.partitionSize = (lastLba - firstLba + 1) * static_cast<uint64_t>(GetDeviceBlockSize());
166 const uint8_t *nameOffset = data + (j * PARTITION_ENTRY_SIZE + GPT_PARTITION_NAME_OFFSET);
167 // 2 bytes for 1 charactor of partition name
168 ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, newPtnInfo.dispName, MAX_GPT_NAME_SIZE / 2);
169 (void)memcpy_s(newPtnInfo.partitionTypeGuid, sizeof(newPtnInfo.partitionTypeGuid),
170 typeGuid, sizeof(typeGuid));
171 newPtnInfo.lun = lun;
172 startIter = ++(partitionInfo_.insert(startIter, newPtnInfo));
173 count++;
174 }
175 }
176 return true;
177 }
178
179
UfsPatchGptHeader(UfsPartitionDataInfo & ptnDataInfo,const uint32_t blockSize)180 void UfsPtable::UfsPatchGptHeader(UfsPartitionDataInfo &ptnDataInfo, const uint32_t blockSize)
181 {
182 uint32_t deviceBlockSize = GetDeviceBlockSize();
183 // mbr len + gptHeader len = 2 blockSize
184 if (blockSize == 0 || ptnDataInfo.writeDataLen < 2 * blockSize || ptnDataInfo.lunSize == 0 ||
185 deviceBlockSize == 0) {
186 LOG(ERROR) << "invaild argument";
187 return;
188 }
189 uint64_t cardSizeSector = ptnDataInfo.lunSize / deviceBlockSize;
190 if (cardSizeSector == 0) {
191 cardSizeSector = DEFAULT_SECTOR_NUM;
192 }
193 // Patching primary header
194 uint8_t *primaryGptHeader = ptnDataInfo.data + blockSize;
195 uint64_t lastUsableSector = cardSizeSector - 1 - (hasBackupPtable_ ? GPT_PTABLE_BACKUP_SIZE : 0);
196 if (reservedSize_ != 0 && lastUsableSector > reservedSize_) {
197 LOG(INFO) << "reserve " << reservedSize_ << "block for " << GetDeviceLunNodePath(ptnDataInfo.lunIndex);
198 lastUsableSector -= reservedSize_;
199 }
200 LOG(INFO) << "cardSizeSector " << cardSizeSector << ", lastUsableSector " << lastUsableSector;
201 PUT_LONG_LONG(primaryGptHeader + BACKUP_HEADER_OFFSET, (cardSizeSector - 1));
202 PUT_LONG_LONG(primaryGptHeader + LAST_USABLE_LBA_OFFSET, lastUsableSector);
203 // Find last partition
204 uint32_t totalPart = 0;
205 while (((TMP_DATA_SIZE - blockSize - blockSize) > totalPart * PARTITION_ENTRY_SIZE) &&
206 (*(primaryGptHeader + blockSize + totalPart * PARTITION_ENTRY_SIZE) != 0)) {
207 totalPart++;
208 }
209 if (totalPart == 0) {
210 LOG(ERROR) << "no partition exist";
211 return;
212 }
213 // Patching last partition
214 uint8_t *lastPartOffset = primaryGptHeader + blockSize + (totalPart - 1) * PARTITION_ENTRY_SIZE;
215 uint64_t lastLba = GET_LLWORD_FROM_BYTE(lastPartOffset + PARTITION_ENTRY_LAST_LBA);
216 uint64_t firstLba = GET_LLWORD_FROM_BYTE(lastPartOffset + FIRST_LBA_OFFSET);
217 // General algorithm : calculate partition size by lba
218 uint64_t partitionSize = (lastLba - firstLba + 1) * deviceBlockSize;
219 std::string partitionName;
220 uint8_t *nameOffset = lastPartOffset + GPT_PARTITION_NAME_OFFSET;
221 // 2 bytes for 1 charactor of partition name
222 ParsePartitionName(nameOffset, MAX_GPT_NAME_SIZE, partitionName, MAX_GPT_NAME_SIZE / 2);
223 if (partitionName == USERDATA_PARTITION || (totalPart == 1 && partitionSize == 0)) {
224 // patch userdata or only one partition
225 PUT_LONG_LONG(lastPartOffset + PARTITION_ENTRY_LAST_LBA, lastUsableSector);
226 LOG(INFO) << "partitionSize=" << partitionSize << ", partition_name:" << partitionName;
227 }
228
229 // Updating CRC of the Partition entry array in both headers
230 uint32_t partCount = GET_LWORD_FROM_BYTE(primaryGptHeader + PARTITION_COUNT_OFFSET);
231 uint32_t entrySize = GET_LWORD_FROM_BYTE(primaryGptHeader + PENTRY_SIZE_OFFSET);
232 // mbr len + gptHeader len = 2 blockSize
233 uint32_t crcValue = CalculateCrc32(ptnDataInfo.data + (blockSize * 2), partCount * entrySize);
234 PUT_LONG(primaryGptHeader + PARTITION_CRC_OFFSET, crcValue);
235 // Clearing CRC fields to calculate
236 PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, 0);
237 crcValue = CalculateCrc32(primaryGptHeader, GPT_CRC_LEN);
238 PUT_LONG(primaryGptHeader + HEADER_CRC_OFFSET, crcValue);
239 return;
240 }
241
242 // 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)243 bool UfsPtable::ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize)
244 {
245 if (ptbImgBuffer == nullptr) {
246 LOG(ERROR) << "input param invalid";
247 return false;
248 }
249
250 uint32_t imgBlockSize = ptableData_.lbaLen; // 512
251 uint32_t deviceBlockSize = GetDeviceBlockSize();
252 if (imgBufSize < ptableData_.emmcGptDataLen + ptableData_.imgLuSize + GetPtableExtraOffset()) {
253 LOG(ERROR) << "input param invalid imgBufSize";
254 return false;
255 }
256
257 SetDeviceLunNum();
258 LOG(INFO) << "lun number of ptable:" << deviceLunNum_;
259
260 for (uint32_t i = 0; i < deviceLunNum_; i++) {
261 UfsPartitionDataInfo newLunPtnDataInfo;
262 (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
263 uint8_t *lunStart = GetPtableImageUfsLunPmbrStart(ptbImgBuffer, i);
264 uint8_t *gptHeaderStart = GetPtableImageUfsLunGptHeaderStart(ptbImgBuffer, i);
265 // first block is mbr, second block is gptHeader
266 if (!CheckProtectiveMbr(lunStart, imgBlockSize) || !CheckIfValidGpt(gptHeaderStart, imgBlockSize)) {
267 newLunPtnDataInfo.isGptVaild = false;
268 ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
269 continue;
270 }
271 // for hisi: change ptable.img(512 bytes/block) into format of device(4096 bytes/block)
272 if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, lunStart, imgBlockSize) != EOK) {
273 LOG(WARNING) << "memcpy_s pmbr fail";
274 }
275 if (memcpy_s(newLunPtnDataInfo.data + deviceBlockSize, TMP_DATA_SIZE - deviceBlockSize,
276 gptHeaderStart, imgBlockSize) != EOK) {
277 LOG(WARNING) << "memcpy_s gpt header fail";
278 }
279 // skip 2 lba length to set gpt entry
280 if (memcpy_s(newLunPtnDataInfo.data + 2 * deviceBlockSize, TMP_DATA_SIZE - 2 * deviceBlockSize,
281 GetPtableImageUfsLunEntryStart(ptbImgBuffer, i), GPT_ENTRYS_SIZE) != EOK) {
282 LOG(WARNING) << "memcpy_s gpt data fail";
283 }
284 newLunPtnDataInfo.writeDataLen = ptableData_.writeDeviceLunSize;
285 newLunPtnDataInfo.lunIndex = i + ptableData_.startLunNumber;
286 newLunPtnDataInfo.lunSize = GetDeviceLunCapacity(newLunPtnDataInfo.lunIndex);
287 UfsPatchGptHeader(newLunPtnDataInfo, deviceBlockSize);
288 newLunPtnDataInfo.isGptVaild = true;
289 ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
290 if (!UfsReadGpt(newLunPtnDataInfo.data, newLunPtnDataInfo.writeDataLen,
291 newLunPtnDataInfo.lunIndex, deviceBlockSize)) {
292 LOG(ERROR) << "parse ufs gpt fail";
293 return false;
294 }
295 }
296 return true;
297 }
298
ReadAndCheckMbr(const uint32_t lunIndex,const uint32_t blockSize)299 bool UfsPtable::ReadAndCheckMbr(const uint32_t lunIndex, const uint32_t blockSize)
300 {
301 if (blockSize <= 0 || lunIndex < 0 || lunIndex > deviceLunNum_) {
302 LOG(ERROR) << "blockSize <= 0";
303 return false;
304 }
305
306 uint8_t *buffer = new(std::nothrow) uint8_t[blockSize]();
307 if (buffer == nullptr) {
308 LOG(ERROR) << "new buffer failed!";
309 return false;
310 }
311 std::string ufsNode = GetDeviceLunNodePath(lunIndex);
312 if (!MemReadWithOffset(ufsNode, 0, buffer, blockSize)) {
313 LOG(ERROR) << "read " << blockSize << " bytes from ufsNode " << ufsNode << " failed!";
314 delete [] buffer;
315 return false;
316 }
317
318 bool result = CheckProtectiveMbr(buffer, blockSize);
319
320 delete [] buffer;
321 return result;
322 }
323
GetLunNumFromNode(const std::string & ufsNode)324 int32_t UfsPtable::GetLunNumFromNode(const std::string &ufsNode)
325 {
326 if (std::char_traits<char>::length(PREFIX_UFS_NODE) + 1 != ufsNode.length()) {
327 LOG(ERROR) << "ufsNode length is " << ufsNode.length() << ", \
328 not equal to PREFIX_UFS_NODE(" << std::char_traits<char>::length(PREFIX_UFS_NODE) << ") + 1";
329 return -1;
330 }
331 char ufsLunIndex = ufsNode.back();
332 // such as : 'a' - 'a'
333 return (ufsLunIndex - 'a');
334 }
335
LoadPartitionInfoFromLun(const uint32_t lunIndex,const uint32_t imgLen)336 bool UfsPtable::LoadPartitionInfoFromLun(const uint32_t lunIndex, const uint32_t imgLen)
337 {
338 if (imgLen == 0 || lunIndex < 0 || lunIndex > deviceLunNum_) {
339 LOG(ERROR) << "imgLen or lunIndex is invaild " << imgLen << " " << lunIndex;
340 return false;
341 }
342 std::string ufsNode = GetDeviceLunNodePath(lunIndex);
343
344 uint8_t *buffer = new(std::nothrow) uint8_t[imgLen]();
345 if (buffer == nullptr) {
346 LOG(ERROR) << "new buffer failed!";
347 return false;
348 }
349 if (!MemReadWithOffset(ufsNode, 0, buffer, imgLen)) {
350 LOG(ERROR) << "read " << imgLen << " bytes from ufsNode " << ufsNode << " failed!";
351 delete [] buffer;
352 return false;
353 }
354 UfsPartitionDataInfo newLunPtnDataInfo;
355 newLunPtnDataInfo.isGptVaild = true;
356 newLunPtnDataInfo.lunIndex = lunIndex;
357 newLunPtnDataInfo.lunSize = imgLen;
358 newLunPtnDataInfo.writeDataLen = imgLen;
359 (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
360 if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, buffer, imgLen) != EOK) {
361 LOG(WARNING) << "memcpy_s mbr fail";
362 }
363
364 ufsPtnDataInfo_.push_back(newLunPtnDataInfo);
365 int32_t result = UfsReadGpt(buffer, imgLen, lunIndex, GetDeviceBlockSize());
366 delete [] buffer;
367 return result;
368 }
369
LoadAllLunPartitions()370 uint32_t UfsPtable::LoadAllLunPartitions()
371 {
372 uint32_t lunIndex;
373 for (lunIndex = 0; lunIndex < deviceLunNum_; lunIndex++) {
374 if (ReadAndCheckMbr(lunIndex, GetDeviceBlockSize())) {
375 LoadPartitionInfoFromLun(lunIndex, ptableData_.writeDeviceLunSize);
376 }
377 }
378 return lunIndex;
379 }
380
LoadPtableFromDevice()381 bool UfsPtable::LoadPtableFromDevice()
382 {
383 if (!partitionInfo_.empty()) {
384 LOG(INFO) << "ptable is already loaded to ram";
385 return true;
386 }
387 SetDeviceLunNum();
388 if (LoadAllLunPartitions() == 0) {
389 LOG(ERROR) << "init ptable to ram fail";
390 return false;
391 }
392 LOG(INFO) << "init ptable to ram ok";
393 return true;
394 }
395
WritePartitionTable()396 bool UfsPtable::WritePartitionTable()
397 {
398 if (ufsPtnDataInfo_.empty()) {
399 LOG(ERROR) << "ufsPtnDataInfo_ is empty, write failed!";
400 return false;
401 }
402 for (uint32_t i = 0; i < ufsPtnDataInfo_.size(); i++) {
403 uint64_t writeDataLen = ufsPtnDataInfo_[i].writeDataLen;
404 std::string ufsNode = GetDeviceLunNodePath(ufsPtnDataInfo_[i].lunIndex);
405 LOG(INFO) << "ufs node name:" << ufsNode << ", writeDataLen = " << writeDataLen;
406
407 if (!ufsPtnDataInfo_[i].isGptVaild) {
408 LOG(WARNING) << "invaild ptable, no need to update";
409 continue;
410 }
411 if (!WriteBufferToPath(ufsNode, 0, ufsPtnDataInfo_[i].data, writeDataLen)) {
412 LOG(ERROR) << "write first gpt fail";
413 return false;
414 }
415 #ifndef UPDATER_UT
416 if (hasBackupPtable_) {
417 LOG(INFO) << "should write back up ptable to device";
418 uint64_t lunSize = GetDeviceLunCapacity(ufsPtnDataInfo_[i].lunIndex);
419 WriteBackupPartitionTable(ufsPtnDataInfo_[i].lunIndex, lunSize);
420 }
421 #endif
422 }
423 return true;
424 }
425
WriteBackupPartitionTable(uint32_t lunIdx,uint64_t lunSize)426 bool UfsPtable::WriteBackupPartitionTable(uint32_t lunIdx, uint64_t lunSize)
427 {
428 if (lunIdx >= ufsPtnDataInfo_.size()) {
429 LOG(ERROR) << "lunIdx invalid , lunIdx = " << lunIdx << ", ufsPtnDataInfo size = " << ufsPtnDataInfo_.size();
430 return false;
431 }
432
433 std::string ufsNode = GetDeviceLunNodePath(lunIdx);
434 uint32_t deviceBlockSize = GetDeviceBlockSize();
435 if (lunSize == 0 || lunSize <= GPT_PTABLE_BACKUP_SIZE * deviceBlockSize) {
436 LOG(ERROR) << "lun size invalid, lun size = " << lunSize;
437 return false;
438 }
439 if (deviceBlockSize == 0) {
440 LOG(ERROR) << "deviceBlockSize is invalid";
441 return false;
442 }
443 uint64_t deviceBackGptEntryOffset = lunSize - GPT_PTABLE_BACKUP_SIZE * deviceBlockSize;
444 uint64_t deviceBackGptHeaderOffset = lunSize - deviceBlockSize;
445 std::unique_ptr<uint8_t[]> backUpHeader = std::make_unique<uint8_t[]>(deviceBlockSize);
446 if (memcpy_s(backUpHeader.get(), deviceBlockSize, ufsPtnDataInfo_[lunIdx].data +
447 deviceBlockSize, deviceBlockSize) != EOK) {
448 LOG(ERROR) << "memcpy error, deviceBlockSize:" << deviceBlockSize;
449 return false;
450 }
451 PatchBackUpGptHeader(backUpHeader.get(), deviceBlockSize, deviceBackGptEntryOffset / deviceBlockSize);
452 if (!WriteBufferToPath(ufsNode, deviceBackGptHeaderOffset, backUpHeader.get(), deviceBlockSize)) {
453 LOG(ERROR) << "write back up gpt header failed, deviceBackGptHeaderOffset = " << deviceBackGptHeaderOffset
454 << ", deviceBlockSize = " << deviceBlockSize;
455 return false;
456 }
457
458 if (!WriteBufferToPath(ufsNode, deviceBackGptEntryOffset, ufsPtnDataInfo_[lunIdx].data +
459 deviceBlockSize * 2, (GPT_PTABLE_BACKUP_SIZE - 1) * deviceBlockSize)) { // 2 : pmbr(1) + gpt header(1)
460 LOG(ERROR) << "write back up gpt entries failed, deviceBackGptEntryOffset = " << deviceBackGptEntryOffset
461 << ", deviceBlockSize = " << deviceBlockSize;
462 return false;
463 }
464 LOG(INFO) << "write backup partition table successful";
465 return true;
466 }
467
GetPtableImageUfsLunPmbrStart(uint8_t * imageBuf,const uint32_t lunIndex)468 uint8_t *UfsPtable::GetPtableImageUfsLunPmbrStart(uint8_t *imageBuf, const uint32_t lunIndex)
469 {
470 uint32_t pmbrStart = ptableData_.emmcGptDataLen + GetPtableExtraOffset() + lunIndex * ptableData_.imgLuSize;
471 LOG(INFO) << "GetPtableImageUfsLunPmbrStart : " << std::hex << pmbrStart << std::dec;
472 return imageBuf + pmbrStart;
473 }
474
GetPtableImageUfsLunGptHeaderStart(uint8_t * imageBuf,const uint32_t lunIndex)475 uint8_t *UfsPtable::GetPtableImageUfsLunGptHeaderStart(uint8_t *imageBuf, const uint32_t lunIndex)
476 {
477 uint32_t gptHeaderStart = ptableData_.emmcGptDataLen + GetPtableExtraOffset() + lunIndex * ptableData_.imgLuSize +
478 ptableData_.lbaLen;
479 LOG(INFO) << "GetPtableImageUfsLunGptHeaderStart : " << std::hex << gptHeaderStart << std::dec;
480 return imageBuf + gptHeaderStart;
481 }
482
GetPtableImageUfsLunEntryStart(uint8_t * imageBuf,const uint32_t lunIndex)483 uint8_t *UfsPtable::GetPtableImageUfsLunEntryStart(uint8_t *imageBuf, const uint32_t lunIndex)
484 {
485 uint32_t entryStart = ptableData_.emmcGptDataLen + GetPtableExtraOffset() + lunIndex * ptableData_.imgLuSize +
486 ptableData_.lbaLen + ptableData_.gptHeaderLen;
487 LOG(INFO) << "GetPtableImageUfsLunEntryStart : " << std::hex << entryStart << std::dec;
488 return imageBuf + entryStart;
489 }
490
EditPartitionBuf(uint8_t * imageBuf,uint64_t imgBufSize,std::vector<PtnInfo> & modifyList)491 bool UfsPtable::EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector<PtnInfo> &modifyList)
492 {
493 if (imageBuf == nullptr || imgBufSize == 0 || modifyList.empty() || ptableData_.blockSize == 0) {
494 LOG(ERROR) << "input invalid";
495 return false;
496 }
497 if (imgBufSize < ptableData_.emmcGptDataLen || deviceLunNum_ == 0) {
498 LOG(ERROR) << "can not get offset, imgBufsize =" << imgBufSize << ",emmcGptDataLen ="
499 << ptableData_.emmcGptDataLen << ", deviceLunNum = " << deviceLunNum_;
500 return false;
501 }
502
503 uint32_t gptSize = ptableData_.imgLuSize;
504 uint32_t imgBlockSize = ptableData_.lbaLen; // 512
505 uint32_t deviceBlockSize = GetDeviceBlockSize(); // 4096 or 512
506 uint32_t startLu = ptableData_.startLunNumber;
507 for (uint32_t i = 0; i < deviceLunNum_; ++i) {
508 UfsPartitionDataInfo newLunPtnDataInfo;
509 (void)memset_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, 0, TMP_DATA_SIZE);
510 std::string ufsNode = GetDeviceLunNodePath(i + startLu);
511 newLunPtnDataInfo.lunSize = GetDeviceLunCapacity(i + startLu);
512 if (newLunPtnDataInfo.lunSize == 0) {
513 LOG(ERROR) << "get devDenisity failed in " << ufsNode;
514 return false;
515 }
516 uint8_t *curGptBuf = GetPtableImageUfsLunPmbrStart(imageBuf, i + startLu);
517 if (!ufsPtnDataInfo_[i].isGptVaild) {
518 continue;
519 }
520 struct GptParseInfo gptInfo(imgBlockSize, deviceBlockSize, newLunPtnDataInfo.lunSize -
521 (hasBackupPtable_ ? (GPT_PTABLE_BACKUP_SIZE * deviceBlockSize) : 0));
522 for (auto &t : modifyList) {
523 if (static_cast<uint32_t>(t.lun) == i + startLu && !ChangeGpt(curGptBuf, gptSize, gptInfo, t)) {
524 LOG(ERROR) << "ChangeGpt failed";
525 return false;
526 }
527 }
528 /* mbr block = 1 block */
529 if (memcpy_s(newLunPtnDataInfo.data, TMP_DATA_SIZE, curGptBuf, imgBlockSize) != EOK) {
530 LOG(WARNING) << "memcpy_s fail";
531 }
532 newLunPtnDataInfo.writeDataLen = ptableData_.writeDeviceLunSize;
533 UfsPatchGptHeader(newLunPtnDataInfo, imgBlockSize);
534 }
535 return true;
536 }
537
GetPtableImageBuffer(uint8_t * imageBuf,const uint32_t imgBufSize)538 bool UfsPtable::GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize)
539 {
540 uint32_t imgBlockSize = ptableData_.lbaLen; // 512
541 uint32_t deviceBlockSize = GetDeviceBlockSize();
542 SetDeviceLunNum();
543 if (imageBuf == nullptr || imgBufSize == 0 ||
544 imgBufSize < ptableData_.emmcGptDataLen + GetPtableExtraOffset() + ptableData_.imgLuSize * deviceLunNum_) {
545 LOG(ERROR) << "input param invalid";
546 return false;
547 }
548 for (uint32_t i = 0; i < deviceLunNum_; ++i) {
549 uint32_t curImgOffset = 0;
550 uint32_t curDevOffset = 0;
551 uint32_t imgOffset = ptableData_.emmcGptDataLen + GetPtableExtraOffset() + ptableData_.imgLuSize * i;
552 /* get ufs node name */
553 std::string ufsNode = GetDeviceLunNodePath(i + ptableData_.startLunNumber);
554 if (!CheckFileExist(ufsNode)) {
555 LOG(ERROR) << "file " << ufsNode << " is not exist";
556 return false;
557 }
558 /* get mbr head */
559 if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, imgBlockSize)) {
560 LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error";
561 return false;
562 }
563 bool isGptExist = CheckProtectiveMbr(imageBuf + curImgOffset + imgOffset, imgBlockSize);
564 curImgOffset += imgBlockSize;
565 curDevOffset += deviceBlockSize;
566 if (!isGptExist) {
567 continue;
568 }
569 /* get gpt head */
570 if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, imgBlockSize)) {
571 LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error";
572 return false;
573 }
574 uint32_t maxPartCount = GET_LWORD_FROM_BYTE(&imageBuf[imgOffset + curImgOffset + PARTITION_COUNT_OFFSET]);
575 uint32_t entrySize = GET_LWORD_FROM_BYTE(&imageBuf[imgOffset + curImgOffset + PENTRY_SIZE_OFFSET]);
576 curImgOffset += imgBlockSize;
577 curDevOffset += deviceBlockSize;
578 /* get gpt buf */
579 uint32_t gptInfoLen = maxPartCount * entrySize;
580 if (!MemReadWithOffset(ufsNode, curDevOffset, imageBuf + curImgOffset + imgOffset, gptInfoLen)) {
581 LOG(ERROR) << "MemReadWithOffset " << ufsNode << " error" << gptInfoLen;
582 return false;
583 }
584 }
585 return true;
586 }
587 } // namespace Updater
588