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 class Ptable { 25 public: 26 Ptable() = default; 27 DISALLOW_COPY_MOVE(Ptable); ~Ptable()28 virtual ~Ptable() {} 29 30 static constexpr uint32_t GPT_PARTITION_TYPE_GUID_LEN = 16; 31 static constexpr const char *PREFIX_SYS_CLASS_BLOCK = "/sys/class/block/sd"; 32 33 struct PtnInfo { 34 uint64_t startAddr {}; 35 uint64_t partitionSize {}; 36 uint8_t partitionTypeGuid[GPT_PARTITION_TYPE_GUID_LEN] {}; 37 uint32_t lun {}; 38 std::string dispName {}; 39 std::string writeMode {"WRITE_RAW"}; 40 std::string writePath {}; 41 }; 42 43 struct GptParseInfo { GptParseInfoGptParseInfo44 GptParseInfo(uint64_t imgBlockSize, uint64_t devBlockSize, uint64_t devDensity) 45 : imgBlockSize(imgBlockSize), devBlockSize(devBlockSize), devDensity(devDensity) {} 46 uint64_t imgBlockSize; 47 uint64_t devBlockSize; 48 uint64_t devDensity; 49 }; 50 std::vector<PtnInfo> GetPtablePartitionInfo() const; 51 uint32_t GetPtablePartitionNum() const; 52 void SetReservedSize(uint64_t reservedSize); 53 bool InitPtable(); 54 uint32_t GetDefaultImageSize() const; 55 void PrintPtableInfo() const; 56 void PrintPtableInfo(const std::vector<PtnInfo> &ptnInfo) const; 57 bool GetPartionInfoByName(const std::string &partitionName, PtnInfo &ptnInfo, int32_t &index); 58 std::vector<PtnInfo>& GetPtablePartitionInfoInstance(); 59 bool LoadPtnInfo(const std::vector<PtnInfo>& ptnInfo); 60 61 virtual bool ParsePartitionFromBuffer(uint8_t *ptbImgBuffer, const uint32_t imgBufSize) = 0; 62 virtual bool LoadPtableFromDevice() = 0; 63 virtual bool WritePartitionTable() = 0; 64 virtual bool EditPartitionBuf(uint8_t *imageBuf, uint64_t imgBufSize, std::vector<PtnInfo> &modifyList) = 0; 65 virtual bool GetPtableImageBuffer(uint8_t *imageBuf, const uint32_t imgBufSize) = 0; AddChildPtable(std::unique_ptr<Ptable> child)66 virtual void AddChildPtable(std::unique_ptr<Ptable> child) {} 67 68 #ifndef UPDATER_UT 69 protected: 70 #else 71 public: 72 #endif 73 const std::string USERDATA_PARTITION = "USERDATA"; 74 static constexpr uint32_t PARTITION_ENTRY_SIZE = 128; 75 static constexpr uint32_t MAX_PARTITION_NUM = 128; 76 static constexpr uint32_t FIRST_LBA_OFFSET = 32; 77 static constexpr uint32_t LAST_LBA_OFFSET = 40; 78 static constexpr uint32_t GPT_PARTITION_NAME_OFFSET = 56; 79 static constexpr uint32_t MAX_GPT_NAME_SIZE = 72; 80 static constexpr uint32_t PARTITION_ENTRIES_OFFSET = 72; 81 static constexpr uint32_t PARTITION_CRC_OFFSET = 88; 82 static constexpr uint32_t GPT_DISP_NAME_LEN = 32; 83 static constexpr uint64_t DEFAULT_SECTOR_NUM = (4 * 1024 * 1024 * 2 - 1); 84 static constexpr uint32_t GPT_HEADER_OFFSET = 24; 85 static constexpr uint32_t BACKUP_HEADER_OFFSET = 32; 86 static constexpr uint32_t PARTITION_ENTRY_OFFSET = 72; 87 static constexpr uint32_t LAST_USABLE_LBA_OFFSET = 48; 88 static constexpr uint32_t PARTITION_ENTRY_LAST_LBA = 40; 89 static constexpr uint32_t PARTITION_COUNT_OFFSET = 80; 90 static constexpr uint32_t PENTRY_SIZE_OFFSET = 84; 91 static constexpr uint32_t HEADER_CRC_OFFSET = 16; 92 static constexpr uint32_t GPT_CRC_LEN = 92; 93 static constexpr uint32_t GPT_ENTRYS_SIZE = 128 * 128; 94 95 // set 32 bits data PUT_LONG(uint8_t * x,const uint32_t y)96 inline void PUT_LONG(uint8_t *x, const uint32_t y) 97 { 98 *(x) = (y) & 0xff; 99 *((x) + 1) = ((y) >> 8) & 0xff; 100 *((x) + 2) = ((y) >> 16) & 0xff; 101 *((x) + 3) = ((y) >> 24) & 0xff; 102 } 103 104 // set 64 bits data PUT_LONG_LONG(uint8_t * x,const uint64_t y)105 inline void PUT_LONG_LONG(uint8_t *x, const uint64_t y) 106 { 107 *(x) = (y) & 0xff; 108 *((x) + 1) = (((y) >> 8) & 0xff); 109 *((x) + 2) = (((y) >> 16) & 0xff); 110 *((x) + 3) = (((y) >> 24) & 0xff); 111 *((x) + 4) = (((y) >> 32) & 0xff); 112 *((x) + 5) = (((y) >> 40) & 0xff); 113 *((x) + 6) = (((y) >> 48) & 0xff); 114 *((x) + 7) = (((y) >> 56) & 0xff); 115 } 116 117 // LWORD = 4 bytes (32 bits) GET_LWORD_FROM_BYTE(const uint8_t * x)118 inline uint32_t GET_LWORD_FROM_BYTE(const uint8_t *x) 119 { 120 uint32_t res = static_cast<unsigned int>(*x) | 121 (static_cast<unsigned int>(*(x + 1)) << 8) | 122 (static_cast<unsigned int>(*(x + 2)) << 16) | 123 (static_cast<unsigned int>(*(x + 3)) << 24); 124 return res; 125 } 126 127 // LLWORD = 8 bytes (64 bits) GET_LLWORD_FROM_BYTE(const uint8_t * x)128 inline uint64_t GET_LLWORD_FROM_BYTE(const uint8_t *x) 129 { 130 uint64_t res = static_cast<unsigned long long>(*x) | 131 (static_cast<unsigned long long>(*(x + 1)) << 8) | 132 (static_cast<unsigned long long>(*(x + 2)) << 16) | 133 (static_cast<unsigned long long>(*(x + 3)) << 24) | 134 (static_cast<unsigned long long>(*(x + 4)) << 32) | 135 (static_cast<unsigned long long>(*(x + 5)) << 40) | 136 (static_cast<unsigned long long>(*(x + 6)) << 48) | 137 (static_cast<unsigned long long>(*(x + 7)) << 56); 138 return res; 139 } 140 141 struct GPTHeaderInfo { 142 uint32_t headerSize {}; 143 uint32_t partitionEntrySize {}; 144 uint32_t maxPartitionCount {}; 145 uint64_t firstUsableLba {}; 146 }; 147 148 struct PtableData { 149 bool dataValid {}; 150 uint32_t emmcGptDataLen {}; 151 uint32_t lbaLen {}; 152 uint32_t gptHeaderLen {}; 153 uint32_t blockSize {}; 154 uint32_t imgLuSize {}; 155 uint32_t startLunNumber {}; 156 uint32_t writeDeviceLunSize {}; 157 uint32_t defaultLunNum {}; 158 }; 159 160 std::vector<PtnInfo> partitionInfo_; 161 PtableData ptableData_; 162 uint64_t reservedSize_ {0}; 163 164 PtableData GetPtableData() const; 165 bool MemReadWithOffset(const std::string &filePath, const uint64_t offset, 166 uint8_t *outData, const uint32_t dataSize); 167 bool CheckProtectiveMbr(const uint8_t *gptImage, const uint32_t imgLen); 168 bool CheckIfValidGpt(const uint8_t *gptImage, const uint32_t gptImageLen); 169 bool GetCapacity(const std::string &filePath, uint64_t &lunCapacity); 170 bool GetPartitionGptHeaderInfo(const uint8_t *buffer, const uint32_t bufferLen, GPTHeaderInfo& gptHeaderInfo); 171 void PatchBackUpGptHeader(uint8_t *gptHeader, const uint32_t len, uint64_t backGptEntryStart); 172 bool PartitionCheckGptHeader(const uint8_t *gptImage, const uint32_t len, const uint64_t lbaNum, 173 const uint32_t blockSize, GPTHeaderInfo& gptHeaderInfo); 174 void ParsePartitionName(const uint8_t *data, const uint32_t dataLen, 175 std::string &name, const uint32_t nameLen); 176 uint32_t CalculateCrc32(const uint8_t *buffer, const uint32_t len); 177 bool WritePtablePartition(const std::string &path, uint64_t offset, const uint8_t *buffer, uint32_t size); 178 bool CheckFileExist(const std::string &fileName); 179 bool WriteBufferToPath(const std::string &path, const uint64_t offset, const uint8_t *buffer, const uint32_t size); 180 bool ChangeGpt(uint8_t *gptBuf, uint64_t gptSize, GptParseInfo gptInfo, PtnInfo &modifyInfo); 181 bool AdjustGpt(uint8_t *ptnInfoBuf, uint64_t bufSize, const std::string &ptnName, uint64_t preLastLBA, 182 uint64_t lastPtnLastLBA); 183 184 private: 185 static constexpr uint64_t MBR_MAGIC_NUM_POS = 0x1FE; 186 static constexpr uint8_t MBR_MAGIC_NUM_0 = 0x55; 187 static constexpr uint8_t MBR_MAGIC_NUM_1 = 0xAA; 188 static constexpr uint32_t MBR_GPT_MAX_NUM = 4; // one disk has most 4 main partitions 189 static constexpr uint32_t MBR_GPT_ENTRY = 0x1BE; 190 static constexpr uint32_t MBR_GPT_ENTRY_SIZE = 0x010; 191 static constexpr uint32_t GPT_TYPE_SIGN_OFFSET = 0x04; 192 static constexpr uint32_t MBR_PROTECTIVE_GPT_TYPE = 0xEE; 193 static constexpr uint64_t EFI_MAGIC_NUMBER = 0x5452415020494645; // GPT SIGNATURE(8 bytes), little-end, (EFI PART) 194 static constexpr uint32_t SECTOR_SIZE = 512; 195 static constexpr uint32_t LBA_LENGTH = SECTOR_SIZE; 196 static constexpr uint32_t HEADER_SIZE_OFFSET = 12; 197 static constexpr uint32_t FIRST_USABLE_LBA_OFFSET = 40; 198 static constexpr uint32_t GPT_HEADER_SIZE = 92; 199 static constexpr uint32_t PRIMARY_HEADER_OFFSET = 24; 200 static constexpr uint32_t MIN_PARTITION_ARRAY_SIZE = 0x4000; 201 202 bool VerifyMbrMagicNum(const uint8_t *buffer, const uint32_t size); 203 uint32_t Reflect(uint32_t data, const uint32_t len); 204 205 bool CheckGptHeader(uint8_t *buffer, const uint32_t bufferLen, const uint64_t lbaNum, 206 const GPTHeaderInfo& gptHeaderInfo); 207 void SetPartitionName(const std::string &name, uint8_t *data, const uint32_t size); 208 bool ParsePtableDataNode(const JsonNode &ptableDataNode); 209 bool ParsePtableData(); 210 }; 211 } // namespace Updater 212 #endif // UPDATER_PTABLE_H 213