|
1 #!perl -w |
|
2 # |
|
3 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 # All rights reserved. |
|
5 # This component and the accompanying materials are made available |
|
6 # under the terms of the License "Eclipse Public License v1.0" |
|
7 # which accompanies this distribution, and is available |
|
8 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
9 # |
|
10 # Initial Contributors: |
|
11 # Nokia Corporation - initial contribution. |
|
12 # |
|
13 # Contributors: |
|
14 # |
|
15 # Description: |
|
16 # |
|
17 use strict; |
|
18 |
|
19 #use Math::BigInt; |
|
20 |
|
21 # |
|
22 # Perl module to create and maintain feature manager data files. |
|
23 # You can either set up the information programmatically or else load up |
|
24 # information from a pre-existing feature data file and then modify it. You |
|
25 # can also save the information to a file (in feature manager dataset format). |
|
26 # |
|
27 # This class maintains header information plus two arrays, one containing |
|
28 # feature flag information and the other containing default supported range |
|
29 # information. Those are themselves objects and have their own accessor |
|
30 # methods. |
|
31 # |
|
32 |
|
33 package HCRdat; |
|
34 |
|
35 use HCRrec; |
|
36 |
|
37 |
|
38 # |
|
39 # n e w |
|
40 # |
|
41 # Create a new HCRdat object. For example 'my $hd = HCRdat->new("filea"); |
|
42 # |
|
43 sub new |
|
44 { |
|
45 my $arg = shift; |
|
46 my $fn = shift; |
|
47 my $class = ref($arg) || $arg; |
|
48 my $self = { |
|
49 fingerprint => "HCRf", # 4 bytes wide. |
|
50 fileversion => 1, # 2 bytes. |
|
51 fileflags => 0x0001, # 2 bytes. |
|
52 numrecords => 0, # 4 bytes. |
|
53 lsdoffset => 0, # 4 bytes. |
|
54 lsdsize => 0, # 4 bytes. |
|
55 packprefix => "V", # Changed with endian-ness. |
|
56 # Used to create binary strings. |
|
57 |
|
58 settingrecords => [], # Array of objects |
|
59 lsd => [], # Array of bytes |
|
60 }; |
|
61 bless $self, $class; |
|
62 return $self; |
|
63 } |
|
64 |
|
65 |
|
66 # Print to STDOUT the header information we have. |
|
67 sub ShowHeader |
|
68 { |
|
69 my $self = shift; |
|
70 return undef unless(ref($self)); |
|
71 |
|
72 # Get header information.. |
|
73 my $typefield = $self->TypeField(); |
|
74 my $fileversion = $self->FileVersion(); |
|
75 my $fileflags = $self->FileFlags(); |
|
76 my $numrecords = $self->NumRecords(); |
|
77 my $lsdoffset = $self->LsdOffset(); |
|
78 my $lsdsize = $self->LsdSize(); |
|
79 |
|
80 # Display it in English. |
|
81 print " FINGERPRINTF: '$typefield'\n"; |
|
82 print " FILEVERSION: '$fileversion'\n"; |
|
83 print " FILEFLAGS: '$fileflags'\n"; |
|
84 print " NUMRECORDS: '$numrecords'\n"; |
|
85 print " LSDOFFSET: '$lsdoffset'\n"; |
|
86 print " LSDSIZE: '$lsdsize'\n"; |
|
87 |
|
88 return(0); |
|
89 } |
|
90 |
|
91 # Get/Set the endian-ness we want. Changes the 'packprefix' member which is |
|
92 # used in the creation of binary data. |
|
93 sub Endian |
|
94 { |
|
95 my $self = shift; |
|
96 return undef unless(ref($self)); |
|
97 my $arg = shift; |
|
98 return $self->{endian} unless(defined($arg)); |
|
99 if($arg =~ m/(LE|BE)/i) |
|
100 { |
|
101 my $endian = uc($1); |
|
102 $self->{endian} = $endian; |
|
103 # Used by 'pack' to generate binary strings. |
|
104 $self->{packprefix} = "V" if($endian eq "LE"); |
|
105 $self->{packprefix} = "N" if($endian eq "BE"); |
|
106 } |
|
107 return $self->{endian}; |
|
108 } |
|
109 |
|
110 # This is the fingerprint. |
|
111 sub TypeField |
|
112 { |
|
113 my $self = shift; |
|
114 return undef unless(ref($self)); |
|
115 my $arg = shift; |
|
116 $self->{fingerprint} = $arg if(defined($arg)); |
|
117 return $self->{fingerprint}; |
|
118 } |
|
119 |
|
120 sub FileVersion |
|
121 { |
|
122 my $self = shift; |
|
123 return undef unless(ref($self)); |
|
124 my $arg = shift; |
|
125 # Should we be testing for a numeric value? |
|
126 $self->{fileversion} = $arg if(defined($arg)); |
|
127 return $self->{fileversion}; |
|
128 } |
|
129 |
|
130 sub FileFlags |
|
131 { |
|
132 my $self = shift; |
|
133 return undef unless(ref($self)); |
|
134 my $arg = shift; |
|
135 $self->{fileflags} = $arg if(defined($arg)); |
|
136 return $self->{fileflags}; |
|
137 } |
|
138 |
|
139 # How many feature flag objects have we got? |
|
140 sub NumRecords |
|
141 { |
|
142 my $self = shift; |
|
143 return undef unless(ref($self)); |
|
144 my $arg = shift; |
|
145 $self->{numrecords} += $arg if(defined($arg)); |
|
146 return $self->{numrecords}; |
|
147 } |
|
148 |
|
149 |
|
150 sub LsdOffset |
|
151 { |
|
152 my $self = shift; |
|
153 return undef unless(ref($self)); |
|
154 my $arg = shift; |
|
155 $self->{lsdoffset} = $arg if(defined($arg)); |
|
156 return $self->{lsdoffset}; |
|
157 } |
|
158 |
|
159 sub LsdSize |
|
160 { |
|
161 my $self = shift; |
|
162 return undef unless(ref($self)); |
|
163 my $arg = shift; |
|
164 $self->{lsdsize} = $arg if(defined($arg)); |
|
165 return $self->{lsdsize}; |
|
166 } |
|
167 |
|
168 # Create a binary string containing the header information for the |
|
169 # feature manager data file based on the various fields in this object. |
|
170 sub CreateBinaryHeader |
|
171 { |
|
172 my $self = shift; |
|
173 return undef unless(ref($self)); |
|
174 my $hdrstring; |
|
175 |
|
176 # Get the letter for packing information with 'pack' into a binary form. |
|
177 my $pack16 = lc($self->{packprefix}); |
|
178 my $pack32 = uc($self->{packprefix}); |
|
179 |
|
180 # Get header information.. |
|
181 my $typefield = $self->TypeField(); |
|
182 my $fileversion = $self->FileVersion(); |
|
183 my $fileflags = $self->FileFlags(); |
|
184 my $numrecords = $self->NumRecords(); |
|
185 my $lsdoffset = $self->LsdOffset(); |
|
186 my $lsdsize = $self->LsdSize(); |
|
187 |
|
188 # Write the 'type' field out. This is 'feat'. Would this be different on |
|
189 # big-endian systems? |
|
190 $hdrstring = $typefield; |
|
191 |
|
192 # Now the file version number. A 16-bit value.. Will this cause trouble |
|
193 # if the shifted value is signed? |
|
194 $hdrstring .= pack($pack16 . "1", $fileversion); |
|
195 |
|
196 # Now the file flags. Another 16-bit value.. |
|
197 $hdrstring .= pack($pack16 . "1", $fileflags); |
|
198 |
|
199 # Now the number of listed features - a 32-bit value. |
|
200 $hdrstring .= pack($pack32 . "1", $numrecords); |
|
201 |
|
202 # Now the number of listed features - a 32-bit value. |
|
203 $hdrstring .= pack($pack32 . "1", $lsdoffset); |
|
204 |
|
205 # Now the number of listed features - a 32-bit value. |
|
206 $hdrstring .= pack($pack32 . "1", $lsdsize); |
|
207 |
|
208 # Now the 3 reserved words |
|
209 $hdrstring .= pack($pack32 . "3", (0, 0, 0)); |
|
210 |
|
211 return $hdrstring; |
|
212 } |
|
213 |
|
214 sub CreateImageHdr |
|
215 { |
|
216 my $self = shift; |
|
217 return undef unless(ref($self)); |
|
218 #my $partid = shift; |
|
219 #return -1 unless(defined($partid)); |
|
220 |
|
221 # Add fingerprint, 1st reserved word and format version |
|
222 my $imghdr = pack "V4", (0x5F524348, 0x54524150, 0x00000000, 0x00000001); |
|
223 # Add space for image size, timestamp, 2nd reserved word |
|
224 $imghdr .= pack "V3", (0x00000000, time, 0x00000000); |
|
225 # Add space for payload checksum, HCR Payload constants: UID and 0x0 flags |
|
226 $imghdr .= pack "V3", (0x00000000, 0x10286AB8, 0x00000000); |
|
227 #Reserved space |
|
228 $imghdr .= pack "x216", (0x00000000); |
|
229 |
|
230 return $imghdr; |
|
231 } |
|
232 |
|
233 sub WriteToImage |
|
234 { |
|
235 my $self = shift; |
|
236 return undef unless(ref($self)); |
|
237 my $imgfile = shift; |
|
238 return -1 unless(defined($imgfile)); |
|
239 my $datfile = shift; |
|
240 return -1 unless(defined($datfile)); |
|
241 #my $partid = shift; |
|
242 #return -1 unless(defined($partid)); |
|
243 my $rc = 0; |
|
244 |
|
245 open IMGFILE, "> $imgfile" or die "Couldn't open file '$imgfile' for writing.\n"; |
|
246 binmode IMGFILE; |
|
247 |
|
248 syswrite(IMGFILE, $self->CreateImageHdr(), 256); |
|
249 |
|
250 open DATFILE, "$datfile" or die "Couldn't open file '$datfile' for reading.\n"; |
|
251 binmode DATFILE; |
|
252 # print FILE $self->BinaryContent(); |
|
253 |
|
254 #my $wordsum = 0x1200000000; |
|
255 #my $wordsum = Math::BigInt->new("0x0220100123"); |
|
256 #printf("test: %x\n", $wordsum->external(); |
|
257 |
|
258 my $imgsize = 256; |
|
259 my $word; |
|
260 printf("-reading image:\n") if ($mhd::otrace); |
|
261 while (sysread (DATFILE, $word, 4)) { |
|
262 #printf ("%08x ",$word) if ($mhd::otrace); |
|
263 my $iword = unpack("V" , $word); |
|
264 printf ("%08x ",$iword) if ($mhd::otrace); |
|
265 $rc = syswrite (IMGFILE, $word, 4); |
|
266 die "error: ($rc) failed to write datfile word into imgfile.\n" if ($rc != 4); |
|
267 #$wordsum->badd($iword); |
|
268 $imgsize += 4; |
|
269 print "\n" if (($mhd::otrace) && ($imgsize%16==0)); |
|
270 } |
|
271 print "\n" if ($mhd::otrace); |
|
272 # ordsum: 0x". $wordsum ."\n" if ($mhd::otrace); |
|
273 my $checksum = 0x12345678; |
|
274 close DATFILE; |
|
275 |
|
276 printf("-image size: %d, checksum: 0x%08x", $imgsize, $checksum) if ($mhd::otrace); |
|
277 |
|
278 $rc = sysseek(IMGFILE, 16, 0); |
|
279 die "error: ($rc) failed to seek in image to write header.\n" if ($rc != 16); |
|
280 |
|
281 # Write out the image size |
|
282 my $imginfo1 = pack "V1", ($imgsize); |
|
283 $rc = syswrite(IMGFILE, $imginfo1, 4); |
|
284 die "error: ($rc) failed to write image size/checksum to image header.\n" if ($rc != 4); |
|
285 |
|
286 $rc = sysseek(IMGFILE, 28, 0); |
|
287 die "error: ($rc) failed to seek in image to write header.\n" if ($rc != 28); |
|
288 |
|
289 # Write out the image checksum |
|
290 my $imginfo2 = pack "V1", ($checksum); |
|
291 $rc = syswrite(IMGFILE, $imginfo2, 4); |
|
292 die "error: ($rc) failed to write image size/checksum to image header.\n" if ($rc != 4); |
|
293 |
|
294 close IMGFILE; |
|
295 |
|
296 return 0; |
|
297 } |
|
298 |
|
299 # Writes the binary file specified as an argument with the content of this |
|
300 # and contained feature flag and dsr objects. |
|
301 sub WriteToFile |
|
302 { |
|
303 my $self = shift; |
|
304 return undef unless(ref($self)); |
|
305 my $file = shift; |
|
306 return undef unless(defined($file)); |
|
307 open FILE, "> $file" or die "Couldn't open file '$file' for writing.\n"; |
|
308 binmode FILE; |
|
309 print FILE $self->BinaryContent(); |
|
310 |
|
311 close FILE; |
|
312 return 0; |
|
313 } |
|
314 |
|
315 |
|
316 # Create the binary equivalent of the internal data and return it as a |
|
317 # string. |
|
318 sub BinaryContent |
|
319 { |
|
320 my $self = shift; |
|
321 return undef unless(ref($self)); |
|
322 |
|
323 # Get the feature flag entries.. This is an array reference. |
|
324 # For each one append the binary representation of the information |
|
325 # contained. |
|
326 my $records = ""; |
|
327 my $lsd = ""; |
|
328 my $ffs_ref = $self->SettingRecords(); |
|
329 my $ff; |
|
330 |
|
331 my $count = 0; |
|
332 foreach $ff (@$ffs_ref) |
|
333 { |
|
334 $count++; |
|
335 printf("-encoding record: %04d (0x%08x:%04d)\n", $count, $ff->CUID(), $ff->EID()); |
|
336 $records .= $ff->GetRecHdrBinary(length ($lsd)); |
|
337 my $stype = $ff->Type(); |
|
338 if (($stype & 0xffff0000) && ($ff->Length() > 0)) { |
|
339 $lsd .= $ff->GetRecLsdBinary(); |
|
340 } |
|
341 } |
|
342 |
|
343 $self->LsdOffset(32+length ($records)); # header size 32 |
|
344 $self->LsdSize(length ($lsd)); |
|
345 |
|
346 my $header = $self->CreateBinaryHeader(); |
|
347 |
|
348 return $header . $records . $lsd; |
|
349 } |
|
350 |
|
351 # Return a reference to the 'feature flags' array. |
|
352 sub SettingRecords |
|
353 { |
|
354 my $self = shift; |
|
355 return undef unless(ref($self)); |
|
356 return $self->{settingrecords}; |
|
357 } |
|
358 |
|
359 # Add a Feature Flag object. Perhaps there should be code to check if we |
|
360 # already know about this feature flag. (i.e check the uid against the ones |
|
361 # we have). |
|
362 sub AddSettingRecord |
|
363 { |
|
364 my $self = shift; |
|
365 return undef unless(ref($self)); |
|
366 my $arg = shift; |
|
367 die "panic: method 'AddSettingRecord' requires a 'HCRrec' object as argument.\n" |
|
368 unless(ref($arg) eq "HCRrec"); |
|
369 |
|
370 push @{$self->SettingRecords()}, $arg; |
|
371 $self->NumRecords(1); |
|
372 |
|
373 return 0; |
|
374 } |
|
375 |
|
376 |
|
377 1; |
|
378 |