• 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 #include "ptable_manager.h"
17 
18 #include "log/log.h"
19 #include "securec.h"
20 
21 namespace Updater {
22 std::string PtableManager::ptbImgTag_ = "";
23 // class PtableManager
PtableManager()24 PtableManager::PtableManager() : pPtable_(nullptr)
25 {
26     InitPtablePtr();
27     PtableManager::ptbImgTag_ = "ptable.img";
28 }
29 
GetDeviceStorageType()30 PtableManager::StorageType PtableManager::GetDeviceStorageType()
31 {
32     return storage_;
33 }
34 
SetDeviceStorageType()35 void PtableManager::SetDeviceStorageType()
36 {
37     if (storage_ != StorageType::STORAGE_UNKNOWN) {
38         return;
39     }
40     if (IsUfsDevice()) {
41         storage_ = StorageType::STORAGE_UFS;
42         LOG(INFO) << "is UFS DEVICE";
43     } else {
44         storage_ = StorageType::STORAGE_EMMC;
45         LOG(INFO) << "is EMMC DEVICE";
46     }
47 }
48 
IsUfsDevice()49 bool PtableManager::IsUfsDevice()
50 {
51     return true;
52 }
53 
ReloadDevicePartition(Hpackage::PkgManager * pkgManager)54 void PtableManager::ReloadDevicePartition(Hpackage::PkgManager *pkgManager)
55 {
56     return LoadPartitionInfo(pkgManager);
57 }
58 
InitPtablePtr()59 void PtableManager::InitPtablePtr()
60 {
61     SetDeviceStorageType();
62     if (pPtable_ == nullptr) {
63         if (GetDeviceStorageType() == StorageType::STORAGE_UFS) {
64             pPtable_ = std::make_unique<UfsPtable>();
65         } else {
66             pPtable_ = nullptr;
67         }
68     }
69 }
70 
InitPtableManager()71 bool PtableManager::InitPtableManager()
72 {
73     if (pPtable_ == nullptr) {
74         LOG(ERROR) << "pPtable_ is nullptr";
75         return false;
76     }
77     if (!pPtable_->InitPtable()) {
78         LOG(ERROR) << "init ptable error";
79         return false;
80     }
81     return true;
82 }
83 
GetPartitionInfoIndexByName(const std::vector<Ptable::PtnInfo> & ptnInfo,const std::string & name)84 int32_t PtableManager::GetPartitionInfoIndexByName(const std::vector<Ptable::PtnInfo> &ptnInfo,
85     const std::string &name)
86 {
87     if (ptnInfo.empty() || name.size() == 0) {
88         LOG(ERROR) << "invalid input: ptnInfo is empty or name is null";
89         return -1;
90     }
91 
92     for (size_t i = 0; i < ptnInfo.size(); i++) {
93         if (ptnInfo[i].dispName == name) {
94             return i;
95         }
96     }
97     return -1;
98 }
99 
IsPartitionChanged(const std::vector<Ptable::PtnInfo> & devicePtnInfo,const std::vector<Ptable::PtnInfo> & pkgPtnInfo,const std::string & partitionName)100 bool PtableManager::IsPartitionChanged(const std::vector<Ptable::PtnInfo> &devicePtnInfo,
101     const std::vector<Ptable::PtnInfo> &pkgPtnInfo, const std::string &partitionName)
102 {
103     if (pkgPtnInfo.empty()) {
104         LOG(INFO) << "No ptable in package. Ptable no changed!";
105         return false;
106     }
107     if (devicePtnInfo.empty()) {
108         LOG(WARNING) << "ptable sizes in device and package are different, partition is changed";
109         return true;
110     }
111     int32_t deviceIndex = GetPartitionInfoIndexByName(devicePtnInfo, partitionName);
112     if (deviceIndex < 0) {
113         LOG(ERROR) << "can't find the " << partitionName << " partition in device ptable!";
114         return true;
115     }
116     int32_t updateIndex = GetPartitionInfoIndexByName(pkgPtnInfo, partitionName);
117     if (updateIndex < 0) {
118         LOG(ERROR) << "can't find the " << partitionName << " partition in package ptable!";
119         return true;
120     }
121     bool ret = false;
122     if (devicePtnInfo[deviceIndex].startAddr != pkgPtnInfo[updateIndex].startAddr) {
123         LOG(INFO) << partitionName << " start address is changed:";
124         LOG(INFO) << "[" << partitionName << "]: device ptable[" << deviceIndex << "] startAddr = 0x" <<
125             devicePtnInfo[deviceIndex].startAddr << ", in package ptable[" << updateIndex << "] startAddr is 0x" <<
126             pkgPtnInfo[updateIndex].startAddr;
127         ret = true;
128     }
129     if (devicePtnInfo[deviceIndex].partitionSize != pkgPtnInfo[updateIndex].partitionSize) {
130         LOG(INFO) << partitionName << " partition size is changed:";
131         LOG(INFO) << "[" << partitionName << "]: device ptable[" << deviceIndex << "] partitionSize = 0x" <<
132             devicePtnInfo[deviceIndex].partitionSize << ", in package ptable[" << updateIndex <<
133             "] partitionSize is 0x" << pkgPtnInfo[updateIndex].partitionSize;
134         ret = true;
135     }
136     return ret;
137 }
138 
IsPtableChanged(const std::vector<Ptable::PtnInfo> & devicePtnInfo,const std::vector<Ptable::PtnInfo> & pkgPtnInfo)139 bool PtableManager::IsPtableChanged(const std::vector<Ptable::PtnInfo> &devicePtnInfo,
140     const std::vector<Ptable::PtnInfo> &pkgPtnInfo)
141 {
142     if (pkgPtnInfo.empty()) {
143         LOG(INFO) << "No ptable in package. Ptable no changed!";
144         return false;
145     }
146     if (devicePtnInfo.empty() || pkgPtnInfo.size() != devicePtnInfo.size()) {
147         LOG(WARNING) << "ptable sizes in device and package are different, ptable is changed";
148         return true;
149     }
150     for (size_t i = 0; i < pkgPtnInfo.size(); i++) {
151         if (devicePtnInfo[i].dispName != pkgPtnInfo[i].dispName) {
152             LOG(WARNING) << "module_name in ptable is different:";
153             LOG(WARNING) << "ptable NAME in device is " << devicePtnInfo[i].dispName <<
154                 ", in package is " << pkgPtnInfo[i].dispName;
155             return true;
156         }
157         if (devicePtnInfo[i].startAddr != pkgPtnInfo[i].startAddr) {
158             LOG(WARNING) << pkgPtnInfo[i].dispName << " start address is different:";
159             LOG(WARNING) << "Device ptable [" << devicePtnInfo[i].dispName << "] startAddr is 0x" <<
160                 devicePtnInfo[i].startAddr;
161             LOG(WARNING) << "Package ptable [" << pkgPtnInfo[i].dispName << "] startAddr is 0x" <<
162                 pkgPtnInfo[i].startAddr;
163             return true;
164         }
165         if (devicePtnInfo[i].partitionSize != pkgPtnInfo[i].partitionSize) {
166             LOG(WARNING) << pkgPtnInfo[i].dispName << " partition size is different:";
167             LOG(WARNING) << "Device ptable [" << devicePtnInfo[i].dispName << "] partitionSize is 0x" <<
168                 devicePtnInfo[i].partitionSize;
169             LOG(WARNING) << "Package ptable [" << pkgPtnInfo[i].dispName << "] partitionSize is 0x" <<
170                 pkgPtnInfo[i].partitionSize;
171             return true;
172         }
173     }
174     return false;
175 }
176 
WritePtableToDevice()177 bool PtableManager::WritePtableToDevice()
178 {
179     if (pPtable_ == nullptr) {
180         LOG(ERROR) << "Write ptable to device failed! pPtable_ is nullptr";
181         return false;
182     }
183     if (!pPtable_->WritePartitionTable()) {
184         LOG(ERROR) << "Write ptable to device failed! Please load ptable first!";
185         return false;
186     }
187     LOG(INFO) << "Write ptable to device success!";
188     return true;
189 }
190 
PrintPtableInfo()191 void PtableManager::PrintPtableInfo()
192 {
193     if (pPtable_ != nullptr) {
194         LOG(ERROR) << "print partition info:";
195         pPtable_->PrintPtableInfo();
196         return;
197     }
198 
199     LOG(INFO) << "print partition info failed!";
200     return;
201 }
202 
GetPartionInfoByName(const std::string & partitionName,Ptable::PtnInfo & ptnInfo,int32_t & index)203 bool PtableManager::GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo, int32_t &index)
204 {
205     if (pPtable_ == nullptr) {
206         LOG(ERROR) << "GetPartionInfoByName failed! pPtable_ is nullptr";
207         return false;
208     }
209     std::string standardPtnName = partitionName;
210     standardPtnName.erase(std::remove(standardPtnName.begin(), standardPtnName.end(), '/'), standardPtnName.end());
211     if (pPtable_->GetPartionInfoByName(standardPtnName, ptnInfo, index)) {
212         LOG(INFO) << "GetPartionInfoByName success!";
213         return true;
214     }
215     LOG(ERROR) << "GetPartionInfoByName failed! Not found " << standardPtnName;
216     return false;
217 }
218 
GetPartionInfoByName(const std::string & partitionName,Ptable::PtnInfo & ptnInfo)219 bool PtableManager::GetPartionInfoByName(const std::string &partitionName, Ptable::PtnInfo &ptnInfo)
220 {
221     int32_t index = -1;
222     return GetPartionInfoByName(partitionName, ptnInfo, index);
223 }
224 
225 // class PackagePtable
PackagePtable()226 PackagePtable::PackagePtable() : PtableManager() {}
227 
LoadPartitionInfo(Hpackage::PkgManager * pkgManager)228 void PackagePtable::LoadPartitionInfo([[maybe_unused]] Hpackage::PkgManager *pkgManager)
229 {
230     if (pkgManager == nullptr) {
231         LOG(ERROR) << "pkgManager is nullptr";
232         return;
233     }
234     if (!InitPtableManager()) {
235         LOG(ERROR) << "init ptable manager error";
236         return;
237     }
238 
239     uint32_t imgBufSize = pPtable_->GetDefaultImageSize();
240     if (imgBufSize <= 0) {
241         LOG(ERROR) << "Invalid imgBufSize";
242         return;
243     }
244     uint8_t *imageBuf = new(std::nothrow) uint8_t[imgBufSize]();
245 
246     if (imageBuf == nullptr) {
247         LOG(ERROR) << "new ptable_buffer error";
248         return;
249     }
250     if (!GetPtableBufferFromPkg(pkgManager, imageBuf, imgBufSize)) {
251         LOG(ERROR) << "get ptable buffer failed";
252         delete [] imageBuf;
253         return;
254     }
255 
256     if (!pPtable_->ParsePartitionFromBuffer(imageBuf, imgBufSize)) {
257         LOG(ERROR) << "get ptable from ptable image buffer failed";
258         delete [] imageBuf;
259         return;
260     }
261     delete [] imageBuf;
262     LOG(INFO) << "print package partition info:";
263     pPtable_->PrintPtableInfo();
264     return;
265 }
266 
GetPtableBufferFromPkg(Hpackage::PkgManager * pkgManager,uint8_t * & imageBuf,uint32_t size)267 bool PackagePtable::GetPtableBufferFromPkg(Hpackage::PkgManager *pkgManager, uint8_t *&imageBuf, uint32_t size)
268 {
269     if (pkgManager == nullptr) {
270         LOG(ERROR) << "pkgManager is nullptr";
271         return false;
272     }
273 
274     const Hpackage::FileInfo *info = pkgManager->GetFileInfo(PtableManager::ptbImgTag_);
275     if (info == nullptr) {
276         info = pkgManager->GetFileInfo("/ptable");
277         if (info == nullptr) {
278             LOG(ERROR) << "Can not get file info " << PtableManager::ptbImgTag_;
279             return false;
280         }
281     }
282 
283     Hpackage::PkgManager::StreamPtr outStream = nullptr;
284     (void)pkgManager->CreatePkgStream(outStream, PtableManager::ptbImgTag_, info->unpackedSize,
285         Hpackage::PkgStream::PkgStreamType_MemoryMap);
286     if (outStream == nullptr) {
287         LOG(ERROR) << "Error to create output stream";
288         return false;
289     }
290 
291     if (pkgManager->ExtractFile(PtableManager::ptbImgTag_, outStream) != Hpackage::PKG_SUCCESS) {
292         LOG(ERROR) << "Error to extract ptable";
293         pkgManager->ClosePkgStream(outStream);
294         return false;
295     }
296 
297     size_t bufSize = 0;
298     uint8_t* buffer = nullptr;
299     outStream->GetBuffer(buffer, bufSize);
300     if (memcpy_s(imageBuf, size, buffer, std::min(static_cast<size_t>(size), bufSize))) {
301         LOG(ERROR) << "memcpy to imageBuf fail";
302         pkgManager->ClosePkgStream(outStream);
303         return false;
304     }
305     pkgManager->ClosePkgStream(outStream);
306     return true;
307 }
308 
309 // class DevicePtable
DevicePtable()310 DevicePtable::DevicePtable() : PtableManager() {}
311 
LoadPartitionInfo(Hpackage::PkgManager * pkgManager)312 void DevicePtable::LoadPartitionInfo([[maybe_unused]] Hpackage::PkgManager *pkgManager)
313 {
314     (void)pkgManager;
315     if (!InitPtableManager()) {
316         LOG(ERROR) << "init ptable manager error";
317         return;
318     }
319     if (!pPtable_->LoadPtableFromDevice()) {
320         LOG(ERROR) << "load device parititon to ram fail";
321         return;
322     }
323 
324     LOG(INFO) << "print device partition info:";
325     pPtable_->PrintPtableInfo();
326     return;
327 }
328 
ComparePartition(PtableManager & newPtbManager,const std::string partitionName)329 bool DevicePtable::ComparePartition(PtableManager &newPtbManager, const std::string partitionName)
330 {
331     if (pPtable_ == nullptr || newPtbManager.pPtable_ == nullptr) {
332         LOG(ERROR) << "input pPtable point is nullptr, compare failed!";
333         return false;
334     }
335     if (IsPartitionChanged(pPtable_->GetPtablePartitionInfo(),
336         newPtbManager.pPtable_->GetPtablePartitionInfo(), partitionName)) {
337         LOG(INFO) << partitionName << " are different";
338         return true;
339     }
340     LOG(INFO) << partitionName << " are the same";
341     return false;
342 }
343 
ComparePtable(PtableManager & newPtbManager)344 bool DevicePtable::ComparePtable(PtableManager &newPtbManager)
345 {
346     if (pPtable_ == nullptr || newPtbManager.pPtable_ == nullptr) {
347         LOG(ERROR) << "input pPtable point is nullptr, compare failed!";
348         return false;
349     }
350     if (IsPtableChanged(pPtable_->GetPtablePartitionInfo(),
351         newPtbManager.pPtable_->GetPtablePartitionInfo())) {
352         LOG(INFO) << "two ptables are different";
353         return true;
354     }
355     LOG(INFO) << "two ptables are the same";
356     return false;
357 }
358 } // namespace Updater
359