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 27namespace Updater { 28uint32_t UfsPtable::GetDeviceLunNum() 29{ 30 return deviceLunNum_; 31} 32 33uint64_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 42uint32_t UfsPtable::GetPtableExtraOffset(void) 43{ 44 return 0; 45} 46 47// avoid u disk being recognized as a valid gpt lun device 48bool 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 67uint32_t UfsPtable::GetDeviceBlockSize(void) 68{ 69 return ptableData_.blockSize; 70} 71 72std::string UfsPtable::GetDeviceLunNodePath(const uint32_t lun) 73{ 74 char lunIndexName = 'a' + lun; 75 return std::string(PREFIX_UFS_NODE) + lunIndexName; 76} 77 78void 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 102bool 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 121bool 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 180void 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 243bool 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 299bool 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 324int32_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 336bool 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 370uint32_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 381bool 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 396bool 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 426bool 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 468uint8_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 475uint8_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 483uint8_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 491bool 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 538bool 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