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