|
1 /* |
|
2 * Copyright (c) 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 "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 using System; |
|
18 using System.Collections.Generic; |
|
19 using System.Text; |
|
20 using System.IO; |
|
21 using SymbianUtils; |
|
22 using SymbianUtils.Tracer; |
|
23 using SymbianUtils.Streams; |
|
24 using SymbianStructuresLib.Uids; |
|
25 using SymbianStructuresLib.Compression.Common; |
|
26 using SymbianImageLib.Common.Content; |
|
27 using SymbianImageLib.Common.Image; |
|
28 using SymbianImageLib.Common.Header; |
|
29 using SymbianImageLib.Common.Streams; |
|
30 using SymbianImageLib.Common.Factory; |
|
31 using SymbianImageLib.ROM.Image; |
|
32 using SymbianImageLib.ROM.Header; |
|
33 using SymbianImageLib.ROM.Structures; |
|
34 |
|
35 namespace SymbianImageLib.ROM.Content |
|
36 { |
|
37 internal class SIContentROM : SIContent |
|
38 { |
|
39 #region Constructors |
|
40 public SIContentROM( SIROM aImage ) |
|
41 : base( aImage ) |
|
42 { |
|
43 SIHeaderROM header = (SIHeaderROM) aImage.Header; |
|
44 base.RelocationAddress = header.RomBaseAddress; |
|
45 } |
|
46 #endregion |
|
47 |
|
48 #region From SymbianImageContentFile |
|
49 public override TSymbianCompressionType CompressionType |
|
50 { |
|
51 get |
|
52 { |
|
53 // Compression type comes from overall image header |
|
54 TSymbianCompressionType ret = base.ImageHeader.CompressionType; |
|
55 return ret; |
|
56 } |
|
57 } |
|
58 |
|
59 public override bool IsRelocationSupported |
|
60 { |
|
61 get { return false; } |
|
62 } |
|
63 |
|
64 public override string FileName |
|
65 { |
|
66 get { return Image.Name; } |
|
67 } |
|
68 |
|
69 public override uint FileSize |
|
70 { |
|
71 get { return (uint) base.Image.Stream.Length; } |
|
72 } |
|
73 |
|
74 public override uint ContentSize |
|
75 { |
|
76 get |
|
77 { |
|
78 // This is not 100% accurate, but hopefully good enough... |
|
79 uint size = (uint) base.ImageStream.Length; |
|
80 return size; |
|
81 } |
|
82 } |
|
83 |
|
84 public override byte[] GetAllData() |
|
85 { |
|
86 // The image ownes a memory stream (if the image has been decompressed) |
|
87 byte[] ret = new byte[ 0 ]; |
|
88 // |
|
89 if ( base.ImageStream is SIMemoryStream ) |
|
90 { |
|
91 SIMemoryStream memStream = (SIMemoryStream) base.ImageStream; |
|
92 ret = memStream.Data; |
|
93 } |
|
94 // |
|
95 return ret; |
|
96 } |
|
97 |
|
98 protected override uint DoProvideDataUInt32( uint aTranslatedAddress ) |
|
99 { |
|
100 using ( SymbianStreamReaderLE reader = Image.Stream.CreateReader( SymbianStreamReaderLE.TCloseOperation.ENone ) ) |
|
101 { |
|
102 reader.Seek( aTranslatedAddress ); |
|
103 uint ret = reader.ReadUInt32(); |
|
104 return ret; |
|
105 } |
|
106 } |
|
107 |
|
108 protected override ushort DoProvideDataUInt16( uint aTranslatedAddress ) |
|
109 { |
|
110 using ( SymbianStreamReaderLE reader = Image.Stream.CreateReader( SymbianStreamReaderLE.TCloseOperation.ENone ) ) |
|
111 { |
|
112 reader.Seek( aTranslatedAddress ); |
|
113 ushort ret = reader.ReadUInt16(); |
|
114 return ret; |
|
115 } |
|
116 } |
|
117 |
|
118 protected override void DoDecompress() |
|
119 { |
|
120 base.Trace( "[SymbianImageContentFileROM] DoDecompress() - START - compression type: {0}", CompressionType ); |
|
121 // |
|
122 switch ( CompressionType ) |
|
123 { |
|
124 case TSymbianCompressionType.ENone: |
|
125 base.Trace( "[SymbianImageContentFileROM] DoDecompress() - not compressed" ); |
|
126 break; |
|
127 case TSymbianCompressionType.EBytePair: |
|
128 base.Trace( "[SymbianImageContentFileROM] DoDecompress() - byte pair" ); |
|
129 DoDecompressBytePair(); |
|
130 break; |
|
131 default: |
|
132 case TSymbianCompressionType.EDeflate: |
|
133 base.Trace( "[SymbianImageContentFileROM] DoDecompress() - unsuporrted compression type" ); |
|
134 throw new NotSupportedException(); |
|
135 } |
|
136 // |
|
137 base.Trace( "[SymbianImageROM] DoDecompress() - END" ); |
|
138 } |
|
139 |
|
140 protected override bool GetIsContentPrepared() |
|
141 { |
|
142 return iContentIsPrepared; |
|
143 } |
|
144 #endregion |
|
145 |
|
146 #region Properties |
|
147 public new SIHeaderROM ImageHeader |
|
148 { |
|
149 get |
|
150 { |
|
151 SIHeaderROM header = (SIHeaderROM) base.ImageHeader; |
|
152 return header; |
|
153 } |
|
154 } |
|
155 #endregion |
|
156 |
|
157 #region Internal methods |
|
158 private void DoDecompressBytePair() |
|
159 { |
|
160 if ( iContentIsPrepared == false ) |
|
161 { |
|
162 SIHeaderROM imageHeader = ImageHeader; |
|
163 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - START - header uncompressed rom size: {0}", imageHeader.UncompressedRomSize ); |
|
164 |
|
165 // Create new buffer and copy over rom image header |
|
166 SIMemoryStream resultantDataStream = new SIMemoryStream( imageHeader.UncompressedRomSize ); |
|
167 |
|
168 int numPages = imageHeader.NumberOfPages; |
|
169 uint pageTableOffset = imageHeader.RomPageIndexOffset; |
|
170 uint romDataOffset = imageHeader.HeaderSizeLoader; |
|
171 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - numPages: {0}, pageTableOffset: {1}, romDataOffset: {2}", numPages, pageTableOffset, romDataOffset ); |
|
172 // |
|
173 SymbianDecompressor decompressor = SymbianDecompressor.NewByType( TSymbianCompressionType.EBytePair ); |
|
174 // |
|
175 List<SRomPageInfo> pages = new List<SRomPageInfo>( numPages + 1 ); |
|
176 for ( int i = 0; i < numPages; i++ ) |
|
177 { |
|
178 // Read a page table entry |
|
179 long pageOffsetWithinFile = pageTableOffset + ( i * SRomPageInfo.Size ); |
|
180 |
|
181 //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - pageOffsetWithinFile: {1}", i, pageOffsetWithinFile ); |
|
182 base.ImageStream.Seek( pageOffsetWithinFile, SeekOrigin.Begin ); |
|
183 SRomPageInfo pageInfo = SRomPageInfo.New( (Stream) base.ImageStream, romDataOffset ); |
|
184 |
|
185 // Process the entry based upon the compression type |
|
186 //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - pageInfo.DataSize: {1}, pageInfo.DataStart: {2}, pageInfo.CompressionType: {3}", i, pageInfo.DataSize, pageInfo.DataStart, pageInfo.CompressionType ); |
|
187 base.ImageStream.Seek( pageInfo.DataStart, SeekOrigin.Begin ); |
|
188 |
|
189 if ( pageInfo.CompressionType == SRomPageInfo.TSymbianCompressionType.ENoCompression ) |
|
190 { |
|
191 // Read data - no decompression needed |
|
192 //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - PAGE NOT COMPRESSED", i ); |
|
193 resultantDataStream.Write( base.ImageStream, (int) pageInfo.DataSize ); |
|
194 } |
|
195 else if ( pageInfo.CompressionType == SRomPageInfo.TSymbianCompressionType.EBytePair ) |
|
196 { |
|
197 //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - BYTE PAIR PAGE", i ); |
|
198 |
|
199 // Read data - need to decompress it |
|
200 byte[] compressedData = new byte[ pageInfo.DataSize ]; |
|
201 base.ImageStream.Read( compressedData, 0, compressedData.Length ); |
|
202 |
|
203 // Make destination buffer - which is a page big |
|
204 byte[] uncompressedData = new byte[ SRomPageInfo.KPageSize ]; |
|
205 |
|
206 // Decompress to buffer - we're handling the page management, so we want raw decompression |
|
207 int error = decompressor.DecompressRaw( compressedData, uncompressedData ); |
|
208 |
|
209 // Save it |
|
210 if ( error < 0 ) |
|
211 { |
|
212 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - Exception - bytepair decompression error", i ); |
|
213 throw new Exception( "BytePair decompression error: " + error.ToString() ); |
|
214 } |
|
215 else if ( error != SRomPageInfo.KPageSize ) |
|
216 { |
|
217 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - Exception - bytepair underflow error", i ); |
|
218 throw new Exception( "Decompressor underflow - only created " + error.ToString() + " bytes" ); |
|
219 } |
|
220 else |
|
221 { |
|
222 resultantDataStream.Write( uncompressedData ); |
|
223 } |
|
224 } |
|
225 else |
|
226 { |
|
227 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - UNSUPPORTED COMPRESSION TYPE - Exception!", i ); |
|
228 throw new NotSupportedException( "Unsupported page compression type" ); |
|
229 } |
|
230 |
|
231 // Report progress |
|
232 base.ReportDecompressionEvent( TDecompressionEvent.EEventDecompressionProgress, ( (float) i / (float) numPages ) * 100 ); |
|
233 } |
|
234 |
|
235 // Now we can replace the base class stream (which is just the raw compressed file data) with the new uncompressed version |
|
236 base.ImageStream = resultantDataStream; |
|
237 iContentIsPrepared = true; |
|
238 |
|
239 base.Trace( "[SymbianImageROM] DoDecompressBytePair() - END" ); |
|
240 } |
|
241 } |
|
242 #endregion |
|
243 |
|
244 #region Data members |
|
245 private bool iContentIsPrepared = false; |
|
246 #endregion |
|
247 } |
|
248 } |