mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-07 10:29:52 +00:00
172 lines
3.0 KiB
Perl
Executable File
172 lines
3.0 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
# ----------------------------------------------------------------------
|
|
# knlinfo by Phil Elwell for Raspberry Pi
|
|
#
|
|
# (c) 2014,2015 Raspberry Pi (Trading) Limited <info@raspberrypi.org>
|
|
#
|
|
# Licensed under the terms of the GNU General Public License.
|
|
# ----------------------------------------------------------------------
|
|
|
|
use strict;
|
|
use integer;
|
|
|
|
use Fcntl ":seek";
|
|
|
|
my $trailer_magic = 'RPTL';
|
|
|
|
my %atom_formats =
|
|
(
|
|
'DDTK' => \&format_bool,
|
|
'DTOK' => \&format_bool,
|
|
'KVer' => \&format_string,
|
|
'270X' => \&format_bool,
|
|
'283X' => \&format_bool,
|
|
'283x' => \&format_bool,
|
|
);
|
|
|
|
if (@ARGV != 1)
|
|
{
|
|
print ("Usage: knlinfo <kernel image>\n");
|
|
exit(1);
|
|
}
|
|
|
|
my $kernel_file = $ARGV[0];
|
|
|
|
|
|
my ($atoms, $pos) = read_trailer($kernel_file);
|
|
|
|
exit(1) if (!$atoms);
|
|
|
|
printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos);
|
|
|
|
foreach my $atom (@$atoms)
|
|
{
|
|
printf(" %s: %s\n", $atom->[0], format_atom($atom));
|
|
}
|
|
|
|
exit(0);
|
|
|
|
sub read_trailer
|
|
{
|
|
my ($kernel_file) = @_;
|
|
my $fh;
|
|
|
|
if (!open($fh, '<', $kernel_file))
|
|
{
|
|
print ("* Failed to open '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
|
|
if (!seek($fh, -12, SEEK_END))
|
|
{
|
|
print ("* seek error in '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
|
|
my $last_bytes;
|
|
sysread($fh, $last_bytes, 12);
|
|
|
|
my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes);
|
|
|
|
if (($magic ne $trailer_magic) || ($data_len != 4))
|
|
{
|
|
print ("* no trailer\n");
|
|
return undef;
|
|
}
|
|
if (!seek($fh, -12, SEEK_END))
|
|
{
|
|
print ("* seek error in '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
|
|
$trailer_len -= 12;
|
|
|
|
while ($trailer_len > 0)
|
|
{
|
|
if ($trailer_len < 8)
|
|
{
|
|
print ("* truncated atom header in trailer\n");
|
|
return undef;
|
|
}
|
|
if (!seek($fh, -8, SEEK_CUR))
|
|
{
|
|
print ("* seek error in '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
$trailer_len -= 8;
|
|
|
|
my $atom_hdr;
|
|
sysread($fh, $atom_hdr, 8);
|
|
my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr);
|
|
|
|
if ($trailer_len < $atom_len)
|
|
{
|
|
print ("* truncated atom data in trailer\n");
|
|
return undef;
|
|
}
|
|
|
|
my $rounded_len = (($atom_len + 3) & ~3);
|
|
if (!seek($fh, -(8 + $rounded_len), SEEK_CUR))
|
|
{
|
|
print ("* seek error in '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
$trailer_len -= $rounded_len;
|
|
|
|
my $atom_data;
|
|
sysread($fh, $atom_data, $atom_len);
|
|
|
|
if (!seek($fh, -$atom_len, SEEK_CUR))
|
|
{
|
|
print ("* seek error in '$kernel_file'\n");
|
|
return undef;
|
|
}
|
|
|
|
push @$atoms, [ $atom_type, $atom_data ];
|
|
}
|
|
|
|
if (($$atoms[-1][0] eq "\x00\x00\x00\x00") &&
|
|
($$atoms[-1][1] eq ""))
|
|
{
|
|
pop @$atoms;
|
|
}
|
|
else
|
|
{
|
|
print ("* end marker missing from trailer\n");
|
|
}
|
|
|
|
return ($atoms, tell($fh));
|
|
}
|
|
|
|
sub format_atom
|
|
{
|
|
my ($atom) = @_;
|
|
|
|
my $format_func = $atom_formats{$atom->[0]} || \&format_hex;
|
|
return $format_func->($atom->[1]);
|
|
}
|
|
|
|
sub format_bool
|
|
{
|
|
my ($data) = @_;
|
|
return unpack('V', $data) ? 'y' : 'n';
|
|
}
|
|
|
|
sub format_int
|
|
{
|
|
my ($data) = @_;
|
|
return unpack('V', $data);
|
|
}
|
|
|
|
sub format_string
|
|
{
|
|
my ($data) = @_;
|
|
return '"'.$data.'"';
|
|
}
|
|
|
|
sub format_hex
|
|
{
|
|
my ($data) = @_;
|
|
return unpack('H*', $data);
|
|
}
|