⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rdmsflsh.pl

📁 dumprom source code,use for learning the dumprom.exe tool for wince
💻 PL
📖 第 1 页 / 共 3 页
字号:
#!perl -w
# (C) 2003-2007 Willem Jan Hengeveld <itsme@xs4all.nl>
# Web: http://www.xs4all.nl/~itsme/
#      http://wiki.xda-developers.com/
#
# $Id: rdmsflsh.pl 1638 2007-11-01 12:31:13Z itsme $
#
# this perl script decodes the IMGFS rom filesystem format
# as used by wm2005 devices
#
# todo: repair import table.
# todo: get this from romhdr.
# todo: add sequence nrs to identically named sections
# 
# problem: files with RELOC section, the reloc section needs more padding.
# 
package Reader;
use strict;
use IO::File;

sub new {
    my ($type, $fh, $base)= @_;
    my $self= bless {
        fh=>$fh,
        baseofs=>$base,
    }, $type;
    return $self;
}
package TyphReader;
use strict;
use IO::File;
our @ISA=qw(Reader);

sub ReadData {
    my ($self, $ofs, $len, $desc)= @_;
    printf("%08lx-%08lx l=%08lx %s\n", $ofs, $ofs+$len, $len, $desc) if ($main::verbose && $desc);
    $self->{fh}->seek($self->cv2file($ofs), SEEK_SET) or return;
    my $data="";
    $self->{fh}->read($data, $len) or return;
    return $data;
}
sub ReadDword {
    my ($self, $ofs, $desc)= @_;
    printf("%08lx-%08lx l=%08lx %s\n", $ofs, $ofs+4, 4, $desc) if ($main::verbose && $desc);
    $self->{fh}->seek($self->cv2file($ofs), SEEK_SET) or return;
    my $data;
    $self->{fh}->read($data, 4) or return;
    return unpack("V", $data);
}
sub cv2file {
    my ($self, $ofs)= @_;
    return $self->{baseofs} + $ofs;
}


package HimaReader;
use strict;
use IO::File;
our @ISA=qw(Reader);

sub ReadData {
    my ($self, $ofs, $len, $desc)= @_;
    printf("%08lx-%08lx l=%08lx %s\n", $ofs, $ofs+$len, $len, $desc) if ($main::verbose && $desc);
    my $data="";
    while ($len) {
        my $want= $len;
        my $realofs= $self->cv2file($ofs);
        $self->{fh}->seek($realofs, SEEK_SET) or return;
        if ($want>0x40000-($realofs&0x3ffff)) {
            $want= 0x40000-($realofs&0x3ffff);
        }

        $self->{fh}->read($data, $want, length($data)) or return;
        $len -= $want;
        $ofs += $want;
    }
    return $data;
}

sub ReadDword {
    my ($self, $ofs, $desc)= @_;
    printf("%08lx-%08lx l=%08lx %s\n", $ofs, $ofs+4, 4, $desc) if ($main::verbose && $desc);
    $self->{fh}->seek($self->cv2file($ofs), SEEK_SET) or return;
    my $data;
    $self->{fh}->read($data, 4) or return;
    return unpack("V", $data);
}

sub cv2file {
    my ($self, $ofs)= @_;
    return $self->{baseofs} + int($ofs/0x3f000)*0x40000+($ofs%0x3f000);
}

package cvtime;
use strict;
use POSIX;

sub convert2unixtime {
    my $wtime= shift;
    my @w= unpack("VV", $wtime);
    return int(($w[1]*(2**32)+$w[0])/10000000.0-11644473600)
}

package main;
use strict;
use Getopt::Long;
use Carp;
use IO::File;
use integer;
use XdaDevelopers::CompressUtils;
$|=1;

#
# i split the wm2005 sp rom apart as follows:
#
# 00000000-00000400  : hdr.nb
# 00000400-00200400  : first xip
# 00200400-00210000  : empty, filled with 0xff
# 00210000-003f0000  : second xip
# 003f0000-01819f00  : imgfs filesystem
# 01819f00-01819f80   signature?
# 01819f80-01b00000   empty 0xff
#
# this script operates on the extracted imgfs part
#

my $reader;
my $outdir;
our $verbose;
my %stats;

sub usage {
    return <<__EOF__
Usage: rdmsflsh [-d savedir] file
__EOF__
}
GetOptions(
    "d=s"=> \$outdir,
    "v"=>\$verbose,
) or die usage();
my $fn= shift or die "usage: need filename\n";
my $fh= IO::File->new($fn, "r") or croak "$fn: $!\n";
binmode $fh;

mkdir $outdir if ($outdir);

# himalaya 80500000
# 00000000: f8 ac 2c 9d e3 d4 2b 4d bd 30 91 6e d8 4f 31 dc
# 00000010: 00000001 00000001 00000001 00000034
# 00000020: 00000040 00001000 00001000 "LZX"
# 00000030: 0000057b 00000020
# 
# typhoon: 003f0000
# 00000000: f8 ac 2c 9d e3 d4 2b 4d bd 30 91 6e d8 4f 31 dc
# 00000010: 00000001 00000001 00000001 00000034
# 00000020: 00000008 00000200 00001000 "XPR"
# 00000030: 00001730 00000100

# universal: 706e0000
# 00000000: f8 ac 2c 9d e3 d4 2b 4d bd 30 91 6e d8 4f 31 dc
# 00000010: 00000001 00000001 00000001 00000034
# 00000020: 00000008 00000200 00001000 "LZX"
# 00000030: 0000ce0c 00000100

my $imgfs_hdr= findimgfs_header($fh) || die "could not find imgfs header\n";

#       universal   tornado0   tornado1   wizard   himalaya   typhoon
# 0000:      ** "MSFLSH50" **
# 0008:      ** 00000000 **
# 000c:      ** 00000038 **                                               size of this header
# 0010:      ** 00000000 **
# 0014:      ** 00000000 **
# 0018: 00000000   00000000   00000000   00000000   00000010   00000000
# 001c: 0000005e   00000048   0000004c   00000060   00000000   0000003f   start block of imgfs
# 0020: 00000080   00000080   00000080   00000080   00000040   00000080   nr of sectors per block
# 0024: 00010000   00010000   00010000   00010000   00040000   00010000   imgfs blocksize
# 0028:      ** 00000000 **
# 002c:      ** 00000001 **
# 0030: 00000000   00000000   00000000   00000000   00000010   00000000
# 0034: 00000000   00000000   00000000   00000000   0000006c   00000000
# 0038: 00000392   000001e8   00000204   00000330   00000000   00000171   nr of blocks in imgfs
# 003c: 00000080   00000080   00000080   00000080   0000003f   00000080   nr of used sectors per block
# 0040: 00010000   00010000   00010000   00010000   00040000   00010000   imgfs blocksize
# 0044: 00000000   00000000   00000000   00000000   00000002   00000000

#      :005e0000: :00480000: :004c0000: :00600000: :00500000: :003f0000:
# 0000:      ** f8ac2c9de3d42b4dbd30916ed84f31dc **                       guidBootSignature
# 0010:      ** 00000001 **                                               dwFSVersion;
# 0014:      ** 00000001 **                                               dwSectorsPerHeaderBlock;
# 0018:      ** 00000001 **                                               dwRunsPerFileHeader;
# 001c:      ** 00000034 **                                               dwBytesPerHeader;
# 0020: 00000008   00000008   00000008   00000008   00000040   00000008   dwChunksPerSector;
# 0024: 00000200   00000200   00000200   00000200   00001000   00000200   dwFirstHeaderBlockOffset;
# 0028:      ** 00001000 **                                               dwDataBlockSize;
# 002c: "LZX"      "LZX"      "LZX"      "LZX"      "LZX"      "XPR"      zCompressionType[4];
# 0030: 0000ce0c   000072a5   00001e72   0000cf31   0000057b   00001730   dwFreeSectorCount;
# 0034: 00000100   00000100   00000100   00000100   00000020   00000100   dwHiddenSectorCount;
# 0038:      ** 00000000 **                                               dwUpdateModeFlag;



# 0000:  magic == f8ac2c9de3d42b4dbd30916ed84f31dc
# 0010:0                                            dwFSVersion;
# 0014:1                                            dwSectorsPerHeaderBlock;
# 0018:2                                            dwRunsPerFileHeader;
# 001c:3  header length == 0x34                     dwBytesPerHeader;
# 0020:4  .. reader type                            dwChunksPerSector;
# 0024:5  .. dir block size                         dwFirstHeaderBlockOffset;
# 0028:6                                            dwDataBlockSize;
# 002c:7  compression magic == "LZX" or == "XPR"    szCompressionType[4];
# 0030:8  .. nr of files                            dwFreeSectorCount;
# 0034:9                                            dwHiddenSectorCount;
# 0038:a                                            dwUpdateModeFlag;

sub findimgfs_header {
    my ($fh)= @_;
    my $signature= pack("H*", "f8ac2c9de3d42b4dbd30916ed84f31dc");
    my $ofs= 0;
    while (1) {
        my $data;
        $fh->seek($ofs, SEEK_SET);
        $fh->read($data, 512) or last;
        my $i= index($data, $signature);
        if ($i>512-40) {
            warn sprintf("ignoring sig at %08lx\n", $ofs+$i);
        }
        elsif ($i>=0) {
            my @hdr= unpack("V7A4V2", substr($data, $i+16));
            if ($hdr[3]==0x34 && ($hdr[7] eq "LZX" || $hdr[7] eq "XPR")) {
                printf("found hdr at %08lx\n", $ofs+$i);
                return {
                    baseofs=>$ofs+$i,
                    compression=>$hdr[7],
                    readertype=>$hdr[4],
                    dirblocksize=>$hdr[5],
                    firstdirofs=>$hdr[5],
                    nroffiles=>$hdr[8],
                };
            }
            else {
                printf("sig at %08lx, but inv hdr: %08lx %s\n", $i+$ofs, $hdr[3], $hdr[7]);
            }
        }
        $ofs += 0x400;
    }
    return undef;
}
my $rd= $imgfs_hdr->{readertype}==8 || $imgfs_hdr->{readertype}==0x20
        ? TyphReader->new($fh, $imgfs_hdr->{baseofs})
        : $imgfs_hdr->{readertype}==0x40
        ? HimaReader->new($fh, $imgfs_hdr->{baseofs})
        : undef;
if (!$rd) {
    die sprintf("could not determine filetype: rd=0x%x base=0x%x\n", $imgfs_hdr->{readertype}, $imgfs_hdr->{baseofs});
}

my $dirdata="";
my $ofs= $imgfs_hdr->{firstdirofs};
while (length($dirdata)==0 || $ofs) {
    my $magic= $rd->ReadDword($ofs, "dirblock magic");
    if ($magic != 0x2f5314ce) {
        carp sprintf("%08lx: magic =%08lx  != 2f5314ce\n", $ofs, $magic);
        last;
    }

    my $dirchunk = $rd->ReadData($ofs+8, $imgfs_hdr->{dirblocksize}-8, sprintf("dirchunk %08lx", $ofs));

    $dirchunk =~ s/(?:\xff\xff\xff\xff)+$//;

    $dirdata .= $dirchunk;

    $ofs= $rd->ReadDword($ofs+4, "dirblock nextptr");
}
my %ref;
for (my $i= 0 ; $i<length($dirdata) ; $i+=4*13)
{
    my $type= unpack("V", substr($dirdata, $i, 4));
    $stats{sprintf("ent_%x", $type)}++;
    if ($type == 0xfffff6fe || $type == 0xfffffefe) {
        my $file= process_fileentry(substr($dirdata, $i, 4*13), sprintf("fileent %d", $i));

        save_file($outdir, $file) if ($outdir);

        printf(" %7d %04x %s %s\n", 
            $file->{size}, 
            $file->{attributes}, 
            POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime $file->{timestamp}),
            $file->{name});
    }
}
print "statistics:\n";
print map { sprintf("%6d [ 0x%08x ] %s\n", $stats{$_}, $stats{$_}, $_) } sort keys %stats;
exit(0);
sub save_data {
    my ($filename, $data)= @_;
    my $fh= IO::File->new($filename, "w") or die "$filename: $!\n";
    binmode $fh;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -