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 #ifndef UPDATER_PTABLE_H 17 #define UPDATER_PTABLE_H 18 #define LAST_PATITION_NAME "USERDATA" 19 20 #include "macros_updater.h" 21 #include "json_node.h" 22 23 namespace Updater { 24 #ifndef UPDATER_UT 25 constexpr const char *PTABLE_TEMP_PATH = "/tmp/update_ptable.img"; 26 constexpr const char *PTABLE_NORMAL_PATH = "/mnt/sys_installer/update_ptable.img"; 27 #else 28 constexpr const char *PTABLE_TEMP_PATH = "/data/update/update_ptable.img"; 29 constexpr const char *PTABLE_NORMAL_PATH = "/data/update/update_ptable.img"; 30 #endif 31 class Ptable { 32 public: 33 Ptable() = default; 34 DISALLOW_COPY_MOVE(Ptable); ~Ptable()35 virtual ~Ptable() {} 36 37 enum class PartType { 38 COMMON_TYPE = 0, 39 A_TYPE, 40 B_TYPE, 41 RESERVED_TYPE 42 }; 43 44 static constexpr uint32_t GPT_PARTITION_TYPE_GUID_LEN = 16; 45 static constexpr const char *PREFIX_SYS_CLASS_BLOCK = "/sys/class/block/sd"; 46 static constexpr const char *PARTITION_NORMAL_TYPE = "normal"; 47 static constexpr const char *PARTITION_AB_TYPE = "ab"; 48 static constexpr const char *PARTITION_A_SUFFIX = "_a"; 49 static constexpr const char *PARTITION_B_SUFFIX = "_b"; 50 static_assert(std::char_traits<char>::length(PARTITION_A_SUFFIX) == 51 std::char_traits<char>::length(PARTITION_B_SUFFIX), "a suffix should equal with b"); 52 static constexpr size_t PARTITION_AB_SUFFIX_SIZE = std::char_traits<char>::length(PARTITION_A_SUFFIX); 53 54 struct PtnInfo { 55 uint64_t startAddr {}; 56 uint64_t partitionSize {}; 57 uint8_t partitionTypeGuid[GPT_PARTITION_TYPE_GUID_LEN] {}; 58 uint32_t lun {}; 59 int gptEntryBufOffset {}; 60 bool isTailPart {false}; 61 std::string dispName {}; 62 PartType partType {PartType::COMMON_TYPE}; 63 std::string writeMode {"WRITE_RAW"}; 64 std::string writePath {}; 65 }; 66 67 struct GptParseInfo { GptParseInfoGptParseInfo68 GptParseInfo(uint64_t imgBlockSize, uint64_t devBlockSize, uint64_t devDensity) 69 : imgBlockSize(imgBlockSize), devBlockSize(devBlockSize), devDensity(devDensity) {} 70 uint64_t imgBlockSize; 71 uint64_t devBlockSize; 72 uint64_t devDensity; 73 }; 74 std::vector<PtnInfo> GetPtablePartitionInfo() const; 75 uint32_t GetPtablePartitionNum() const; 76 void SetReservedSize(uint64_t reservedSize); 77 bool InitPtable(); 78 uint32_t GetDefaultImageSize() const; 79 void PrintPtableInfo() const; 80 void PrintPtableInfo(const std::vector<PtnInfo> &ptnInfo) const; 81 bool GetPartionInfoByName(const std::string &partitionName, PtnInfo &ptnInfo, int32_t &index); 82 std::vector<PtnInfo>& GetPtablePartitionInfoInstance(); 83 bool LoadPtnInfo(const std::vector<PtnInfo>& ptnInfo); 84 bool ReadPartitionFileToBuffer(uint8_t *ptbImgBuffer, uint32_t &imgBufSize); 85 void DeletePartitionTmpFile(); 86 87 virtual bool WritePartitionBufToFile(uint8_t *ptbImgBuffer, const uint32_t imgBufSize); 88 virtual bool ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize) = 0; 89 virtual bool LoadPtableFromDevice() = 0; 90 virtual bool WritePartitionTable() = 0; 91 virtual bool EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector<PtnInfo> &modifyList) = 0; 92 virtual bool GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize) = 0; AddChildPtable(std::unique_ptr<Ptable> child)93 virtual void AddChildPtable(std::unique_ptr<Ptable> child) {} 94 virtual bool CorrectBufByPtnList(uint8_t *imageBuf, uint64_t imgBufSize, const std::vector<PtnInfo> &srcInfo, 95 const std::vector<PtnInfo> &dstInfo); 96 virtual bool SyncABLunPtableDevice(const int sourceSlot); 97 virtual bool GetABLunPartitionInfo(const int sourceSlot, std::string &srcNode, 98 std::string &tgtNode, uint32_t &offset); 99 virtual void ClearPartitionInfo(); 100 GetEndPtnIndex()101 int GetEndPtnIndex() 102 { 103 return endPtnIndex_; 104 } 105 GetUsrDataPtnIndex()106 int GetUsrDataPtnIndex() 107 { 108 return usrDataPtnIndex_; 109 } 110 SetUsrDataPtnIndex(int usrDataPtnIndex)111 void SetUsrDataPtnIndex(int usrDataPtnIndex) 112 { 113 usrDataPtnIndex_ = usrDataPtnIndex; 114 } 115 HasTailPart()116 bool HasTailPart() 117 { 118 return hasTailpart_; 119 } 120 ClearPtnInfo()121 void ClearPtnInfo() 122 { 123 partitionInfo_.clear(); 124 } 125 126 #ifndef UPDATER_UT 127 protected: 128 #else 129 public: 130 #endif 131 const std::string USERDATA_PARTITION = "USERDATA"; 132 static constexpr uint32_t PARTITION_ENTRY_SIZE = 128; 133 static constexpr uint32_t MAX_PARTITION_NUM = 128; 134 static constexpr uint32_t FIRST_LBA_OFFSET = 32; 135 static constexpr uint32_t LAST_LBA_OFFSET = 40; 136 static constexpr uint32_t GPT_PARTITION_NAME_OFFSET = 56; 137 static constexpr uint32_t MAX_GPT_NAME_SIZE = 72; 138 static constexpr uint32_t PARTITION_ENTRIES_OFFSET = 72; 139 static constexpr uint32_t PARTITION_CRC_OFFSET = 88; 140 static constexpr uint32_t GPT_DISP_NAME_LEN = 32; 141 static constexpr uint64_t DEFAULT_SECTOR_NUM = (4 * 1024 * 1024 * 2 - 1); 142 static constexpr uint32_t GPT_HEADER_OFFSET = 24; 143 static constexpr uint32_t BACKUP_HEADER_OFFSET = 32; 144 static constexpr uint32_t PARTITION_ENTRY_OFFSET = 72; 145 static constexpr uint32_t LAST_USABLE_LBA_OFFSET = 48; 146 static constexpr uint32_t PARTITION_ENTRY_LAST_LBA = 40; 147 static constexpr uint32_t PARTITION_COUNT_OFFSET = 80; 148 static constexpr uint32_t PENTRY_SIZE_OFFSET = 84; 149 static constexpr uint32_t HEADER_CRC_OFFSET = 16; 150 static constexpr uint32_t GPT_CRC_LEN = 92; 151 static constexpr uint32_t GPT_ENTRYS_SIZE = 128 * 128; 152 153 // set 32 bits data PUT_LONG(uint8_t * x,const uint32_t y)154 inline void PUT_LONG(uint8_t *x, const uint32_t y) 155 { 156 *(x) = (y) & 0xff; 157 *((x) + 1) = ((y) >> 8) & 0xff; 158 *((x) + 2) = ((y) >> 16) & 0xff; 159 *((x) + 3) = ((y) >> 24) & 0xff; 160 } 161 162 // set 64 bits data PUT_LONG_LONG(uint8_t * x,const uint64_t y)163 inline void PUT_LONG_LONG(uint8_t *x, const uint64_t y) 164 { 165 *(x) = (y) & 0xff; 166 *((x) + 1) = (((y) >> 8) & 0xff); 167 *((x) + 2) = (((y) >> 16) & 0xff); 168 *((x) + 3) = (((y) >> 24) & 0xff); 169 *((x) + 4) = (((y) >> 32) & 0xff); 170 *((x) + 5) = (((y) >> 40) & 0xff); 171 *((x) + 6) = (((y) >> 48) & 0xff); 172 *((x) + 7) = (((y) >> 56) & 0xff); 173 } 174 175 // LWORD = 4 bytes (32 bits) GET_LWORD_FROM_BYTE(const uint8_t * x)176 inline uint32_t GET_LWORD_FROM_BYTE(const uint8_t *x) 177 { 178 uint32_t res = static_cast<unsigned int>(*x) | 179 (static_cast<unsigned int>(*(x + 1)) << 8) | 180 (static_cast<unsigned int>(*(x + 2)) << 16) | 181 (static_cast<unsigned int>(*(x + 3)) << 24); 182 return res; 183 } 184 185 // LLWORD = 8 bytes (64 bits) GET_LLWORD_FROM_BYTE(const uint8_t * x)186 inline uint64_t GET_LLWORD_FROM_BYTE(const uint8_t *x) 187 { 188 uint64_t res = static_cast<unsigned long long>(*x) | 189 (static_cast<unsigned long long>(*(x + 1)) << 8) | 190 (static_cast<unsigned long long>(*(x + 2)) << 16) | 191 (static_cast<unsigned long long>(*(x + 3)) << 24) | 192 (static_cast<unsigned long long>(*(x + 4)) << 32) | 193 (static_cast<unsigned long long>(*(x + 5)) << 40) | 194 (static_cast<unsigned long long>(*(x + 6)) << 48) | 195 (static_cast<unsigned long long>(*(x + 7)) << 56); 196 return res; 197 } 198 199 struct GPTHeaderInfo { 200 uint32_t headerSize {}; 201 uint32_t partitionEntrySize {}; 202 uint32_t maxPartitionCount {}; 203 uint64_t firstUsableLba {}; 204 }; 205 206 struct PtableData { 207 bool dataValid {}; 208 uint32_t emmcGptDataLen {}; 209 uint32_t lbaLen {}; 210 uint32_t gptHeaderLen {}; 211 uint32_t blockSize {}; 212 uint32_t imgLuSize {}; 213 uint32_t startLunNumber {}; 214 uint32_t writeDeviceLunSize {}; 215 uint32_t defaultLunNum {}; 216 }; 217 218 std::vector<PtnInfo> partitionInfo_; 219 PtableData ptableData_; 220 uint64_t reservedSize_ {0}; 221 222 int startPtnIndex_ {-1}; 223 int endPtnIndex_ {-1}; 224 int usrDataPtnIndex_ {-1}; 225 bool hasTailpart_ {false}; 226 227 PtableData GetPtableData() const; 228 bool MemReadWithOffset(const std::string &filePath, const uint64_t offset, 229 uint8_t *outData, const uint32_t dataSize); 230 bool CheckProtectiveMbr(const uint8_t *gptImage, const uint32_t imgLen); 231 bool CheckIfValidGpt(const uint8_t *gptImage, const uint32_t gptImageLen); 232 bool GetCapacity(const std::string &filePath, uint64_t &lunCapacity); 233 bool GetPartitionGptHeaderInfo(const uint8_t *buffer, const uint32_t bufferLen, GPTHeaderInfo& gptHeaderInfo); 234 void PatchBackUpGptHeader(uint8_t *gptHeader, const uint32_t len, uint64_t backGptEntryStart); 235 bool PartitionCheckGptHeader(const uint8_t *gptImage, const uint32_t len, const uint64_t lbaNum, 236 const uint32_t blockSize, GPTHeaderInfo& gptHeaderInfo); 237 void ParsePartitionName(const uint8_t *data, const uint32_t dataLen, 238 std::string &name, const uint32_t nameLen); 239 bool WritePartitionName(const std::string &name, const uint32_t nameLen, uint8_t *data, const uint32_t dataLen); 240 uint32_t CalculateCrc32(const uint8_t *buffer, const uint32_t len); 241 bool WritePtablePartition(const std::string &path, uint64_t offset, const uint8_t *buffer, uint32_t size); 242 bool CheckFileExist(const std::string &fileName); 243 bool WriteBufferToPath(const std::string &path, const uint64_t offset, const uint8_t *buffer, const uint32_t size); 244 bool ChangeGpt(uint8_t *gptBuf, uint64_t gptSize, GptParseInfo gptInfo, PtnInfo &modifyInfo); 245 bool AdjustGpt(uint8_t *ptnInfoBuf, uint64_t bufSize, const std::string &ptnName, uint64_t preLastLBA, 246 uint64_t lastPtnLastLBA); 247 void SetPartitionType(const std::string &partName, PtnInfo &ptnInfo); 248 249 private: 250 static constexpr uint64_t MBR_MAGIC_NUM_POS = 0x1FE; 251 static constexpr uint8_t MBR_MAGIC_NUM_0 = 0x55; 252 static constexpr uint8_t MBR_MAGIC_NUM_1 = 0xAA; 253 static constexpr uint32_t MBR_GPT_MAX_NUM = 4; // one disk has most 4 main partitions 254 static constexpr uint32_t MBR_GPT_ENTRY = 0x1BE; 255 static constexpr uint32_t MBR_GPT_ENTRY_SIZE = 0x010; 256 static constexpr uint32_t GPT_TYPE_SIGN_OFFSET = 0x04; 257 static constexpr uint32_t MBR_PROTECTIVE_GPT_TYPE = 0xEE; 258 static constexpr uint64_t EFI_MAGIC_NUMBER = 0x5452415020494645; // GPT SIGNATURE(8 bytes), little-end, (EFI PART) 259 static constexpr uint32_t SECTOR_SIZE = 512; 260 static constexpr uint32_t LBA_LENGTH = SECTOR_SIZE; 261 static constexpr uint32_t HEADER_SIZE_OFFSET = 12; 262 static constexpr uint32_t FIRST_USABLE_LBA_OFFSET = 40; 263 static constexpr uint32_t GPT_HEADER_SIZE = 92; 264 static constexpr uint32_t PRIMARY_HEADER_OFFSET = 24; 265 static constexpr uint32_t MIN_PARTITION_ARRAY_SIZE = 0x4000; 266 267 bool VerifyMbrMagicNum(const uint8_t *buffer, const uint32_t size); 268 uint32_t Reflect(uint32_t data, const uint32_t len); 269 270 bool CheckGptHeader(uint8_t *buffer, const uint32_t bufferLen, const uint64_t lbaNum, 271 const GPTHeaderInfo& gptHeaderInfo); 272 void SetPartitionName(const std::string &name, uint8_t *data, const uint32_t size); 273 bool ParsePtableDataNode(const JsonNode &ptableDataNode); 274 bool ParsePtableData(); 275 }; 276 } // namespace Updater 277 #endif // UPDATER_PTABLE_H 278