• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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