|
1 /* |
|
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalComponent |
|
22 @released |
|
23 */ |
|
24 #ifdef _MSC_VER |
|
25 #pragma warning (disable: 4786) |
|
26 #endif // _MSC_VER |
|
27 // |
|
28 // Note: This file may contain code to generate corrupt files for test purposes. |
|
29 // Such code is excluded from production builds by use of compiler defines; |
|
30 // it is recommended that such code should be removed if this code is ever published publicly. |
|
31 // |
|
32 |
|
33 #include <iostream> |
|
34 #include <stdio.h> |
|
35 #include <string> |
|
36 #include <sys/stat.h> |
|
37 |
|
38 #include "siscontents.h" |
|
39 #include "utils.h" |
|
40 #include "utility_interface.h" |
|
41 |
|
42 #include <fstream> |
|
43 |
|
44 CSISContents::TStub CSISContents::iStub = CSISContents::EStubNone; |
|
45 |
|
46 |
|
47 |
|
48 void CSISContents::InsertMembers () |
|
49 { |
|
50 InsertMember (iControllerChecksum); |
|
51 InsertMember (iDataChecksum); |
|
52 InsertMember (iController); |
|
53 InsertMember (iData); |
|
54 } |
|
55 |
|
56 |
|
57 CSISContents::CSISContents (const CSISContents& aInitialiser) : |
|
58 CStructure <CSISFieldRoot::ESISContents> (aInitialiser), |
|
59 iControllerChecksum (aInitialiser.iControllerChecksum), |
|
60 iDataChecksum (aInitialiser.iDataChecksum), |
|
61 iController (aInitialiser.iController), |
|
62 iData (aInitialiser.iData) |
|
63 { |
|
64 InsertMembers (); |
|
65 } |
|
66 |
|
67 bool CSISContents::IsSisFile(const std::wstring& aFileName) |
|
68 { |
|
69 TSISStream input; |
|
70 std::wstring fileName = FixPathDelimiters(aFileName); |
|
71 HANDLE file = ::MakeSISOpenFile(fileName.c_str(),GENERIC_READ,OPEN_EXISTING); |
|
72 CSISException::ThrowIf ((INVALID_HANDLE_VALUE == file), |
|
73 CSISException::EFileProblem, std::wstring (L"cannot open ") + fileName); |
|
74 bool success = input.import (file, NULL); |
|
75 ::CloseHandle(file); |
|
76 CSISException::ThrowIf (! success, CSISException::EFileProblem, std::wstring (L"cannot read ") + fileName); |
|
77 return IsSisFile(input); |
|
78 } |
|
79 |
|
80 bool CSISContents::IsSisFile(TSISStream& aStream) |
|
81 { |
|
82 CSISUid::TUid uid [4]; |
|
83 aStream.seek (0); |
|
84 aStream >> uid [0] >> uid [1] >> uid [2] >> uid [3]; |
|
85 bool isSisFile = false; |
|
86 if( uid [0] == KUidSISXApp ) |
|
87 { |
|
88 isSisFile = true; |
|
89 } |
|
90 else if(uid[2] == KUidLegacySisFile) |
|
91 { |
|
92 throw CSISException (CSISException::ELegacyFormat, L"file is a unspported legacy SIS file."); |
|
93 } |
|
94 |
|
95 return isSisFile; |
|
96 } |
|
97 |
|
98 |
|
99 void CSISContents::Load (const std::wstring& aFileName, TUint64* size) |
|
100 { |
|
101 TSISStream input; |
|
102 std::wstring fileName = FixPathDelimiters(aFileName); |
|
103 HANDLE file = ::MakeSISOpenFile(fileName.c_str(),GENERIC_READ,OPEN_EXISTING); |
|
104 if (INVALID_HANDLE_VALUE == file) |
|
105 { |
|
106 SISLogger::Log(L" Error : Cannot open file : "); |
|
107 SISLogger::Log(fileName); |
|
108 SISLogger::Log(L"\n"); |
|
109 throw CSISException (CSISException::EFileProblem, std::wstring (L"cannot open ") + fileName); |
|
110 } |
|
111 bool success = input.import (file, size); |
|
112 ::CloseHandle(file); |
|
113 if(!success) |
|
114 { |
|
115 SISLogger::Log(L" Error : Cannot read file : "); |
|
116 SISLogger::Log(fileName); |
|
117 SISLogger::Log(L"\n"); |
|
118 throw CSISException (CSISException::EFileProblem, std::wstring (L"cannot read ") + fileName); |
|
119 } |
|
120 CSISUid::TUid uid [4]; |
|
121 input.seek (0); |
|
122 input >> uid [0] >> uid [1] >> uid [2] >> uid [3]; |
|
123 if( uid [0] != KUidSISXApp ) |
|
124 { |
|
125 SISLogger::Log(fileName); |
|
126 SISLogger::Log(L" is not a SIS file .\n"); |
|
127 if(uid[2] == KUidLegacySisFile) |
|
128 { |
|
129 throw CSISException (CSISException::ELegacyFormat, fileName + L" is a unspported legacy SIS file."); |
|
130 } |
|
131 throw CSISException (CSISException::EFileFormat, fileName + L" is not a SIS file."); |
|
132 } |
|
133 |
|
134 CSISException::ThrowIf (uid [3] != UidChecksum (uid [0], uid [1], uid [2]), |
|
135 CSISException::EFileFormat, |
|
136 std::wstring (fileName) + L" has invalid UID checksum"); |
|
137 Read (input, input.length ()); |
|
138 Verify (LanguageCount ()); |
|
139 } |
|
140 |
|
141 void CSISContents::Save (const std::wstring& aFileName) const |
|
142 { |
|
143 TSISStream output; |
|
144 if (iStub == EStubROM) |
|
145 { |
|
146 iController.Content ().Write (output, false); |
|
147 } |
|
148 else |
|
149 { |
|
150 OutputHeaderUids (output); |
|
151 Write (output, false); |
|
152 } |
|
153 // remove R/O attributes from file in case it exists already |
|
154 _wchmod(aFileName.c_str(),_S_IREAD | _S_IWRITE); |
|
155 HANDLE file = ::MakeSISOpenFile(aFileName.c_str(),GENERIC_WRITE,CREATE_ALWAYS); |
|
156 CSISException::ThrowIf ((INVALID_HANDLE_VALUE == file), |
|
157 CSISException::EFileProblem, std::wstring (L"cannot create ") + aFileName); |
|
158 bool written = output.exportfile (file); |
|
159 ::CloseHandle(file); |
|
160 if (! written) |
|
161 { |
|
162 ::MakeSISDeleteFile(aFileName.c_str()); |
|
163 throw CSISException (CSISException::EFileProblem, std::wstring (L"cannot write to ") + aFileName); |
|
164 } |
|
165 } |
|
166 |
|
167 |
|
168 |
|
169 TCRC CSISContents::UIDCheck (const void *pPtr) |
|
170 { |
|
171 const unsigned char *pB = reinterpret_cast <const unsigned char *> (pPtr); |
|
172 const unsigned char *pE = pB + (KUidInstallCount * sizeof (CSISUid::TUid)); |
|
173 unsigned char buf [(KUidInstallCount * sizeof(DWORD))>>1]; |
|
174 unsigned char *pT = (&buf[0]); |
|
175 while (pB < pE) |
|
176 { |
|
177 *pT++ = (*pB); |
|
178 pB += 2; |
|
179 } |
|
180 TCRC reply (0); |
|
181 DoTheCrc (reply, reinterpret_cast <const TUint8*> (buf), (KUidInstallCount * sizeof(DWORD))>>1); |
|
182 return reply; |
|
183 } |
|
184 |
|
185 void CSISContents::OutputHeaderUids (TSISStream& output) const |
|
186 { |
|
187 CSISUid::TUid uid [KUidInstallCount + 1]; |
|
188 uid [0] = KUidSISXApp; |
|
189 uid [1] = 0; // Reserved for future use |
|
190 uid [2] = UID1 (); |
|
191 uid [3] = UidChecksum (uid [0], uid [1], uid [2]); |
|
192 for (unsigned short index = 0; index <= KUidInstallCount; index++) |
|
193 { |
|
194 output << uid [index]; |
|
195 } |
|
196 } |
|
197 |
|
198 CSISUid::TUid CSISContents::UidChecksum (const CSISUid::TUid aUid1, const CSISUid::TUid aUid2, const CSISUid::TUid aUid3) |
|
199 { |
|
200 CSISUid::TUid uid [3]; |
|
201 |
|
202 uid [0] = aUid1; |
|
203 uid [1] = aUid2; |
|
204 uid [2] = aUid3; |
|
205 |
|
206 TCRC crcHigh (UIDCheck ((reinterpret_cast <char*> (uid)) + 1)); |
|
207 TCRC crcLow (UIDCheck (reinterpret_cast <char*> (uid))); |
|
208 return static_cast <CSISUid::TUid> ((static_cast <unsigned int> (crcHigh) << 16) + static_cast <unsigned int> (crcLow)); |
|
209 } |
|
210 |
|
211 void CSISContents::EmbedFile (const std::wstring& aFile, const CSISUid::TUid& aUid, CSISInstallBlock& aInstall) |
|
212 { |
|
213 EmbedPackage (aInstall, aFile, aUid); |
|
214 } |
|
215 |
|
216 void CSISContents::EmbedPackage (CSISInstallBlock& aInstallBlock, const std::wstring& aFile, const CSISUid::TUid& aUid) |
|
217 { |
|
218 std::auto_ptr<CSISContents> embed (new CSISContents()); |
|
219 embed->Load (aFile); |
|
220 |
|
221 //makesis doesn't support embedded packages of type PA and PP. |
|
222 if(embed->iData.Stub ()) |
|
223 { |
|
224 SISLogger::Log(aFile); |
|
225 SISLogger::Log(L" is a stub.\t \n"); |
|
226 SISLogger::Log(L"WARNING : Embedded Preinstalled Stub (PA/PP type) SIS file is not supported.\n"); |
|
227 throw CSISException (CSISException::EFileFormat, "Stub File"); |
|
228 } |
|
229 |
|
230 if (aUid != 0) |
|
231 { |
|
232 CSISException::ThrowIf (embed->UID1 () != aUid, CSISException::EUID, aFile + L" contains incorrect UID"); |
|
233 } |
|
234 TUint32 index = iData.AppendData (embed->iData); |
|
235 if (index > 0) |
|
236 { |
|
237 embed->SetDataIndex (index); |
|
238 } |
|
239 aInstallBlock.Embed (embed->iController.Content (), index); |
|
240 } |
|
241 |
|
242 void CSISContents::Verify (const TUint32 aLanguages) const |
|
243 { |
|
244 assert (aLanguages == LanguageCount ()); |
|
245 CSISException::ThrowIf (aLanguages == 0, CSISException::ELanguage, "no languages defined"); |
|
246 CStructure <CSISFieldRoot::ESISContents>::Verify (aLanguages); |
|
247 } |
|
248 |
|
249 |
|
250 void CSISContents::PrepareCrcs () |
|
251 { |
|
252 if ((iDbgFlag & EDbgDataChecksum) == 0) |
|
253 { |
|
254 iDataChecksum.Set (iData.Crc ()); |
|
255 } |
|
256 if ((iDbgFlag & EDbgControllerChecksum) == 0) |
|
257 { |
|
258 iControllerChecksum.Set (iController.Crc ()); |
|
259 } |
|
260 } |
|
261 |
|
262 void CSISContents::WriteSIS (std::wstring aTargetFileName) |
|
263 { |
|
264 MakeNeat (); // MakeNeat () should ensure at least one language defined |
|
265 assert (LanguageCount () > 0); |
|
266 |
|
267 switch (iStub) |
|
268 { |
|
269 case EStubPreInstalled : |
|
270 iController.Content ().SetNow (); |
|
271 iData.SetStub (); |
|
272 iDataChecksum.Set(0); |
|
273 SetDebugOption(EDbgDataChecksum); |
|
274 break; |
|
275 case EStubROM : |
|
276 { |
|
277 // The below piece of code tries to put .sis extension not .SIS as target sisfile name. |
|
278 std::wstring::size_type count (aTargetFileName.size ()); |
|
279 if ( (count >= 4) && |
|
280 (aTargetFileName [count - 4] == L'.')) |
|
281 { |
|
282 count -= 3; |
|
283 std::wstring extension (aTargetFileName.substr (count)); |
|
284 if ( (toupper(extension [0]) == L'S') && |
|
285 (toupper(extension [1]) == L'I') && |
|
286 (toupper(extension [2]) == L'S')) |
|
287 { |
|
288 aTargetFileName = aTargetFileName.substr (0, count); |
|
289 aTargetFileName += std::wstring (L"sis"); |
|
290 } |
|
291 } |
|
292 } |
|
293 // Leave the date and time initialised to 1st Jan 2004, so that ROM stub |
|
294 // files don't change every time they are built. |
|
295 break; |
|
296 default: |
|
297 iController.Content ().SetNow (); |
|
298 break; |
|
299 } |
|
300 |
|
301 PrepareCrcs (); |
|
302 Verify (LanguageCount ()); |
|
303 #ifdef GENERATE_ERRORS |
|
304 if (CSISFieldRoot::IsAnyBugSet ()) |
|
305 { |
|
306 CreateDefects (); |
|
307 } |
|
308 #endif // GENERATE_ERRORS |
|
309 |
|
310 Save (aTargetFileName); |
|
311 } |
|
312 |
|
313 void CSISContents::AddPackageEntry(std::wostream& aStream, bool aVerbose) const |
|
314 { |
|
315 iControllerChecksum.AddPackageEntry(aStream, aVerbose); |
|
316 iDataChecksum.AddPackageEntry(aStream, aVerbose); |
|
317 iController.AddPackageEntry(aStream, aVerbose); // CSISCompressed |
|
318 Controller().AddPackageEntry(aStream, aVerbose); |
|
319 iData.AddPackageEntry(aStream, aVerbose); |
|
320 } |