0049-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. From b2f75aacf0bfb9e3069bdec7a6481ed4bf7a2b51 Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <phil@raspberrypi.org>
  3. Date: Mon, 11 May 2015 09:00:42 +0100
  4. Subject: [PATCH 049/381] scripts: Add mkknlimg and knlinfo scripts from tools
  5. repo
  6. The Raspberry Pi firmware looks for a trailer on the kernel image to
  7. determine whether it was compiled with Device Tree support enabled.
  8. If the firmware finds a kernel without this trailer, or which has a
  9. trailer indicating that it isn't DT-capable, it disables DT support
  10. and reverts to using ATAGs.
  11. The mkknlimg utility adds that trailer, having first analysed the
  12. image to look for signs of DT support and the kernel version string.
  13. knlinfo displays the contents of the trailer in the given kernel image.
  14. scripts/mkknlimg: Add support for ARCH_BCM2835
  15. Add a new trailer field indicating whether this is an ARCH_BCM2835
  16. build, as opposed to MACH_BCM2708/9. If the loader finds this flag
  17. is set it changes the default base dtb file name from bcm270x...
  18. to bcm283y...
  19. Also update knlinfo to show the status of the field.
  20. scripts/mkknlimg: Improve ARCH_BCM2835 detection
  21. The board support code contains sufficient strings to be able to
  22. distinguish 2708 vs. 2835 builds, so remove the check for
  23. bcm2835-pm-wdt which could exist in either.
  24. Also, since the canned configuration is no longer built in (it's
  25. a module), remove the config string checking.
  26. See: https://github.com/raspberrypi/linux/issues/1157
  27. ---
  28. scripts/knlinfo | 168 ++++++++++++++++++++++++++++++++++++++
  29. scripts/mkknlimg | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
  30. 2 files changed, 412 insertions(+)
  31. create mode 100755 scripts/knlinfo
  32. create mode 100755 scripts/mkknlimg
  33. --- /dev/null
  34. +++ b/scripts/knlinfo
  35. @@ -0,0 +1,168 @@
  36. +#!/usr/bin/env perl
  37. +# ----------------------------------------------------------------------
  38. +# knlinfo by Phil Elwell for Raspberry Pi
  39. +#
  40. +# (c) 2014,2015 Raspberry Pi (Trading) Limited <info@raspberrypi.org>
  41. +#
  42. +# Licensed under the terms of the GNU General Public License.
  43. +# ----------------------------------------------------------------------
  44. +
  45. +use strict;
  46. +use integer;
  47. +
  48. +use Fcntl ":seek";
  49. +
  50. +my $trailer_magic = 'RPTL';
  51. +
  52. +my %atom_formats =
  53. +(
  54. + 'DTOK' => \&format_bool,
  55. + 'KVer' => \&format_string,
  56. + '283x' => \&format_bool,
  57. +);
  58. +
  59. +if (@ARGV != 1)
  60. +{
  61. + print ("Usage: knlinfo <kernel image>\n");
  62. + exit(1);
  63. +}
  64. +
  65. +my $kernel_file = $ARGV[0];
  66. +
  67. +
  68. +my ($atoms, $pos) = read_trailer($kernel_file);
  69. +
  70. +exit(1) if (!$atoms);
  71. +
  72. +printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos);
  73. +
  74. +foreach my $atom (@$atoms)
  75. +{
  76. + printf(" %s: %s\n", $atom->[0], format_atom($atom));
  77. +}
  78. +
  79. +exit(0);
  80. +
  81. +sub read_trailer
  82. +{
  83. + my ($kernel_file) = @_;
  84. + my $fh;
  85. +
  86. + if (!open($fh, '<', $kernel_file))
  87. + {
  88. + print ("* Failed to open '$kernel_file'\n");
  89. + return undef;
  90. + }
  91. +
  92. + if (!seek($fh, -12, SEEK_END))
  93. + {
  94. + print ("* seek error in '$kernel_file'\n");
  95. + return undef;
  96. + }
  97. +
  98. + my $last_bytes;
  99. + sysread($fh, $last_bytes, 12);
  100. +
  101. + my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes);
  102. +
  103. + if (($magic ne $trailer_magic) || ($data_len != 4))
  104. + {
  105. + print ("* no trailer\n");
  106. + return undef;
  107. + }
  108. + if (!seek($fh, -12, SEEK_END))
  109. + {
  110. + print ("* seek error in '$kernel_file'\n");
  111. + return undef;
  112. + }
  113. +
  114. + $trailer_len -= 12;
  115. +
  116. + while ($trailer_len > 0)
  117. + {
  118. + if ($trailer_len < 8)
  119. + {
  120. + print ("* truncated atom header in trailer\n");
  121. + return undef;
  122. + }
  123. + if (!seek($fh, -8, SEEK_CUR))
  124. + {
  125. + print ("* seek error in '$kernel_file'\n");
  126. + return undef;
  127. + }
  128. + $trailer_len -= 8;
  129. +
  130. + my $atom_hdr;
  131. + sysread($fh, $atom_hdr, 8);
  132. + my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr);
  133. +
  134. + if ($trailer_len < $atom_len)
  135. + {
  136. + print ("* truncated atom data in trailer\n");
  137. + return undef;
  138. + }
  139. +
  140. + my $rounded_len = (($atom_len + 3) & ~3);
  141. + if (!seek($fh, -(8 + $rounded_len), SEEK_CUR))
  142. + {
  143. + print ("* seek error in '$kernel_file'\n");
  144. + return undef;
  145. + }
  146. + $trailer_len -= $rounded_len;
  147. +
  148. + my $atom_data;
  149. + sysread($fh, $atom_data, $atom_len);
  150. +
  151. + if (!seek($fh, -$atom_len, SEEK_CUR))
  152. + {
  153. + print ("* seek error in '$kernel_file'\n");
  154. + return undef;
  155. + }
  156. +
  157. + push @$atoms, [ $atom_type, $atom_data ];
  158. + }
  159. +
  160. + if (($$atoms[-1][0] eq "\x00\x00\x00\x00") &&
  161. + ($$atoms[-1][1] eq ""))
  162. + {
  163. + pop @$atoms;
  164. + }
  165. + else
  166. + {
  167. + print ("* end marker missing from trailer\n");
  168. + }
  169. +
  170. + return ($atoms, tell($fh));
  171. +}
  172. +
  173. +sub format_atom
  174. +{
  175. + my ($atom) = @_;
  176. +
  177. + my $format_func = $atom_formats{$atom->[0]} || \&format_hex;
  178. + return $format_func->($atom->[1]);
  179. +}
  180. +
  181. +sub format_bool
  182. +{
  183. + my ($data) = @_;
  184. + return unpack('V', $data) ? 'true' : 'false';
  185. +}
  186. +
  187. +sub format_int
  188. +{
  189. + my ($data) = @_;
  190. + return unpack('V', $data);
  191. +}
  192. +
  193. +sub format_string
  194. +{
  195. + my ($data) = @_;
  196. + return '"'.$data.'"';
  197. +}
  198. +
  199. +sub format_hex
  200. +{
  201. + my ($data) = @_;
  202. + return unpack('H*', $data);
  203. +}
  204. --- /dev/null
  205. +++ b/scripts/mkknlimg
  206. @@ -0,0 +1,244 @@
  207. +#!/usr/bin/env perl
  208. +# ----------------------------------------------------------------------
  209. +# mkknlimg by Phil Elwell for Raspberry Pi
  210. +# based on extract-ikconfig by Dick Streefland
  211. +#
  212. +# (c) 2009,2010 Dick Streefland <dick@streefland.net>
  213. +# (c) 2014,2015 Raspberry Pi (Trading) Limited <info@raspberrypi.org>
  214. +#
  215. +# Licensed under the terms of the GNU General Public License.
  216. +# ----------------------------------------------------------------------
  217. +
  218. +use strict;
  219. +use warnings;
  220. +use integer;
  221. +
  222. +my $trailer_magic = 'RPTL';
  223. +
  224. +my $tmpfile1 = "/tmp/mkknlimg_$$.1";
  225. +my $tmpfile2 = "/tmp/mkknlimg_$$.2";
  226. +
  227. +my $dtok = 0;
  228. +my $is_283x = 0;
  229. +
  230. +while (@ARGV && ($ARGV[0] =~ /^-/))
  231. +{
  232. + my $arg = shift(@ARGV);
  233. + if ($arg eq '--dtok')
  234. + {
  235. + $dtok = 1;
  236. + }
  237. + elsif ($arg eq '--283x')
  238. + {
  239. + $is_283x = 1;
  240. + }
  241. + else
  242. + {
  243. + print ("* Unknown option '$arg'\n");
  244. + usage();
  245. + }
  246. +}
  247. +
  248. +usage() if (@ARGV != 2);
  249. +
  250. +my $kernel_file = $ARGV[0];
  251. +my $out_file = $ARGV[1];
  252. +
  253. +if (! -r $kernel_file)
  254. +{
  255. + print ("* File '$kernel_file' not found\n");
  256. + usage();
  257. +}
  258. +
  259. +my @wanted_strings =
  260. +(
  261. + 'bcm2708_fb',
  262. + 'brcm,bcm2835-mmc',
  263. + 'brcm,bcm2835-sdhost',
  264. + 'brcm,bcm2708-pinctrl',
  265. + 'brcm,bcm2835-gpio',
  266. + 'brcm,bcm2835',
  267. + 'brcm,bcm2836'
  268. +);
  269. +
  270. +my $res = try_extract($kernel_file, $tmpfile1);
  271. +$res = try_decompress('\037\213\010', 'xy', 'gunzip', 0,
  272. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  273. +$res = try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1,
  274. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  275. +$res = try_decompress('BZh', 'xy', 'bunzip2', 0,
  276. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  277. +$res = try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0,
  278. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  279. +$res = try_decompress('\211\114\132', 'xy', 'lzop -d', 0,
  280. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  281. +$res = try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1,
  282. + $kernel_file, $tmpfile1, $tmpfile2) if (!$res);
  283. +
  284. +my $append_trailer;
  285. +my $trailer;
  286. +my $kver = '?';
  287. +
  288. +$append_trailer = $dtok;
  289. +
  290. +if ($res)
  291. +{
  292. + $kver = $res->{''} || '?';
  293. + print("Version: $kver\n");
  294. +
  295. + $append_trailer = $dtok;
  296. + if (!$dtok)
  297. + {
  298. + if (config_bool($res, 'bcm2708_fb') ||
  299. + config_bool($res, 'brcm,bcm2835-mmc') ||
  300. + config_bool($res, 'brcm,bcm2835-sdhost'))
  301. + {
  302. + $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl');
  303. + $dtok ||= config_bool($res, 'brcm,bcm2835-gpio');
  304. + $is_283x ||= config_bool($res, 'brcm,bcm2835');
  305. + $is_283x ||= config_bool($res, 'brcm,bcm2836');
  306. + $dtok ||= $is_283x;
  307. + $append_trailer = 1;
  308. + }
  309. + else
  310. + {
  311. + print ("* This doesn't look like a Raspberry Pi kernel. In pass-through mode.\n");
  312. + }
  313. + }
  314. +}
  315. +elsif (!$dtok)
  316. +{
  317. + print ("* Is this a valid kernel? In pass-through mode.\n");
  318. +}
  319. +
  320. +if ($append_trailer)
  321. +{
  322. + printf("DT: %s\n", $dtok ? "y" : "n");
  323. + printf("283x: %s\n", $is_283x ? "y" : "n");
  324. +
  325. + my @atoms;
  326. +
  327. + push @atoms, [ $trailer_magic, pack('V', 0) ];
  328. + push @atoms, [ 'KVer', $kver ];
  329. + push @atoms, [ 'DTOK', pack('V', $dtok) ];
  330. + push @atoms, [ '283x', pack('V', $is_283x) ];
  331. +
  332. + $trailer = pack_trailer(\@atoms);
  333. + $atoms[0]->[1] = pack('V', length($trailer));
  334. +
  335. + $trailer = pack_trailer(\@atoms);
  336. +}
  337. +
  338. +my $ofh;
  339. +my $total_len = 0;
  340. +
  341. +if ($out_file eq $kernel_file)
  342. +{
  343. + die "* Failed to open '$out_file' for append\n"
  344. + if (!open($ofh, '>>', $out_file));
  345. + $total_len = tell($ofh);
  346. +}
  347. +else
  348. +{
  349. + die "* Failed to open '$kernel_file'\n"
  350. + if (!open(my $ifh, '<', $kernel_file));
  351. + die "* Failed to create '$out_file'\n"
  352. + if (!open($ofh, '>', $out_file));
  353. +
  354. + my $copybuf;
  355. + while (1)
  356. + {
  357. + my $bytes = sysread($ifh, $copybuf, 64*1024);
  358. + last if (!$bytes);
  359. + syswrite($ofh, $copybuf, $bytes);
  360. + $total_len += $bytes;
  361. + }
  362. + close($ifh);
  363. +}
  364. +
  365. +if ($trailer)
  366. +{
  367. + # Pad to word-alignment
  368. + syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3));
  369. + syswrite($ofh, $trailer);
  370. +}
  371. +
  372. +close($ofh);
  373. +
  374. +exit($trailer ? 0 : 1);
  375. +
  376. +END {
  377. + unlink($tmpfile1) if ($tmpfile1);
  378. + unlink($tmpfile2) if ($tmpfile2);
  379. +}
  380. +
  381. +
  382. +sub usage
  383. +{
  384. + print ("Usage: mkknlimg [--dtok] [--283x] <vmlinux|zImage|bzImage> <outfile>\n");
  385. + exit(1);
  386. +}
  387. +
  388. +sub try_extract
  389. +{
  390. + my ($knl, $tmp) = @_;
  391. +
  392. + my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`;
  393. +
  394. + return undef if (!$ver);
  395. +
  396. + chomp($ver);
  397. +
  398. + my $res = { ''=>$ver };
  399. + my $string_pattern = '^('.join('|', @wanted_strings).')$';
  400. +
  401. + my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`;
  402. + foreach my $match (@matches)
  403. + {
  404. + chomp($match);
  405. + $res->{$match} = 1;
  406. + }
  407. +
  408. + return $res;
  409. +}
  410. +
  411. +
  412. +sub try_decompress
  413. +{
  414. + my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_;
  415. +
  416. + my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`;
  417. + if ($pos)
  418. + {
  419. + chomp($pos);
  420. + $pos = (split(/[\r\n]+/, $pos))[$idx];
  421. + return undef if (!defined($pos));
  422. + $pos =~ s/:.*[\r\n]*$//s;
  423. + my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null";
  424. + my $err = (system($cmd) >> 8);
  425. + return undef if (($err != 0) && ($err != 2));
  426. +
  427. + return try_extract($tmp2, $tmp1);
  428. + }
  429. +
  430. + return undef;
  431. +}
  432. +
  433. +sub pack_trailer
  434. +{
  435. + my ($atoms) = @_;
  436. + my $trailer = pack('VV', 0, 0);
  437. + for (my $i = $#$atoms; $i>=0; $i--)
  438. + {
  439. + my $atom = $atoms->[$i];
  440. + $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]);
  441. + }
  442. + return $trailer;
  443. +}
  444. +
  445. +sub config_bool
  446. +{
  447. + my ($configs, $wanted) = @_;
  448. + my $val = $configs->{$wanted} || 'n';
  449. + return (($val eq 'y') || ($val eq '1'));
  450. +}