Skip to content

Commit df3b9c6

Browse files
author
Phil Elwell
committed
scripts: Add mkknlimg and knlinfo scripts from tools repo
The Raspberry Pi firmware looks for a trailer on the kernel image to determine whether it was compiled with Device Tree support enabled. If the firmware finds a kernel without this trailer, or which has a trailer indicating that it isn't DT-capable, it disables DT support and reverts to using ATAGs. The mkknlimg utility adds that trailer, having first analysed the image to look for signs of DT support and the kernel version string. knlinfo displays the contents of the trailer in the given kernel image.
1 parent 41a5ce7 commit df3b9c6

File tree

2 files changed

+427
-0
lines changed

2 files changed

+427
-0
lines changed

scripts/knlinfo

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#!/usr/bin/env perl
2+
# ----------------------------------------------------------------------
3+
# knlinfo by Phil Elwell for Raspberry Pi
4+
#
5+
# (c) 2014,2015 Raspberry Pi (Trading) Limited <[email protected]>
6+
#
7+
# Licensed under the terms of the GNU General Public License.
8+
# ----------------------------------------------------------------------
9+
10+
use strict;
11+
use integer;
12+
13+
use Fcntl ":seek";
14+
15+
my $trailer_magic = 'RPTL';
16+
17+
my %atom_formats =
18+
(
19+
'DTOK' => \&format_bool,
20+
'KVer' => \&format_string,
21+
);
22+
23+
if (@ARGV != 1)
24+
{
25+
print ("Usage: knlinfo <kernel image>\n");
26+
exit(1);
27+
}
28+
29+
my $kernel_file = $ARGV[0];
30+
31+
32+
my ($atoms, $pos) = read_trailer($kernel_file);
33+
34+
exit(1) if (!$atoms);
35+
36+
printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos);
37+
38+
foreach my $atom (@$atoms)
39+
{
40+
printf(" %s: %s\n", $atom->[0], format_atom($atom));
41+
}
42+
43+
exit(0);
44+
45+
sub read_trailer
46+
{
47+
my ($kernel_file) = @_;
48+
my $fh;
49+
50+
if (!open($fh, '<', $kernel_file))
51+
{
52+
print ("* Failed to open '$kernel_file'\n");
53+
return undef;
54+
}
55+
56+
if (!seek($fh, -12, SEEK_END))
57+
{
58+
print ("* seek error in '$kernel_file'\n");
59+
return undef;
60+
}
61+
62+
my $last_bytes;
63+
sysread($fh, $last_bytes, 12);
64+
65+
my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes);
66+
67+
if (($magic ne $trailer_magic) || ($data_len != 4))
68+
{
69+
print ("* no trailer\n");
70+
return undef;
71+
}
72+
if (!seek($fh, -12, SEEK_END))
73+
{
74+
print ("* seek error in '$kernel_file'\n");
75+
return undef;
76+
}
77+
78+
$trailer_len -= 12;
79+
80+
while ($trailer_len > 0)
81+
{
82+
if ($trailer_len < 8)
83+
{
84+
print ("* truncated atom header in trailer\n");
85+
return undef;
86+
}
87+
if (!seek($fh, -8, SEEK_CUR))
88+
{
89+
print ("* seek error in '$kernel_file'\n");
90+
return undef;
91+
}
92+
$trailer_len -= 8;
93+
94+
my $atom_hdr;
95+
sysread($fh, $atom_hdr, 8);
96+
my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr);
97+
98+
if ($trailer_len < $atom_len)
99+
{
100+
print ("* truncated atom data in trailer\n");
101+
return undef;
102+
}
103+
104+
my $rounded_len = (($atom_len + 3) & ~3);
105+
if (!seek($fh, -(8 + $rounded_len), SEEK_CUR))
106+
{
107+
print ("* seek error in '$kernel_file'\n");
108+
return undef;
109+
}
110+
$trailer_len -= $rounded_len;
111+
112+
my $atom_data;
113+
sysread($fh, $atom_data, $atom_len);
114+
115+
if (!seek($fh, -$atom_len, SEEK_CUR))
116+
{
117+
print ("* seek error in '$kernel_file'\n");
118+
return undef;
119+
}
120+
121+
push @$atoms, [ $atom_type, $atom_data ];
122+
}
123+
124+
if (($$atoms[-1][0] eq "\x00\x00\x00\x00") &&
125+
($$atoms[-1][1] eq ""))
126+
{
127+
pop @$atoms;
128+
}
129+
else
130+
{
131+
print ("* end marker missing from trailer\n");
132+
}
133+
134+
return ($atoms, tell($fh));
135+
}
136+
137+
sub format_atom
138+
{
139+
my ($atom) = @_;
140+
141+
my $format_func = $atom_formats{$atom->[0]} || \&format_hex;
142+
return $format_func->($atom->[1]);
143+
}
144+
145+
sub format_bool
146+
{
147+
my ($data) = @_;
148+
return unpack('V', $data) ? 'true' : 'false';
149+
}
150+
151+
sub format_int
152+
{
153+
my ($data) = @_;
154+
return unpack('V', $data);
155+
}
156+
157+
sub format_string
158+
{
159+
my ($data) = @_;
160+
return '"'.$data.'"';
161+
}
162+
163+
sub format_hex
164+
{
165+
my ($data) = @_;
166+
return unpack('H*', $data);
167+
}

0 commit comments

Comments
 (0)