1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl 2*b2441318SGreg Kroah-Hartman# SPDX-License-Identifier: GPL-2.0 32221a6eeSDavid Howells# 4cb77f0d6SKamil Rytarowskiuse warnings; 52221a6eeSDavid Howellsuse strict; 62221a6eeSDavid Howellsuse Math::BigInt; 72221a6eeSDavid Howellsuse Fcntl "SEEK_SET"; 82221a6eeSDavid Howells 92221a6eeSDavid Howellsdie "Format: $0 [-s <systemmap-file>] <vmlinux-file> <keyring-file>\n" 102221a6eeSDavid Howells if ($#ARGV != 1 && $#ARGV != 3 || 112221a6eeSDavid Howells $#ARGV == 3 && $ARGV[0] ne "-s"); 122221a6eeSDavid Howells 132221a6eeSDavid Howellsmy $sysmap = ""; 142221a6eeSDavid Howellsif ($#ARGV == 3) { 152221a6eeSDavid Howells shift; 162221a6eeSDavid Howells $sysmap = $ARGV[0]; 172221a6eeSDavid Howells shift; 182221a6eeSDavid Howells} 192221a6eeSDavid Howells 202221a6eeSDavid Howellsmy $vmlinux = $ARGV[0]; 212221a6eeSDavid Howellsmy $keyring = $ARGV[1]; 222221a6eeSDavid Howells 232221a6eeSDavid Howells# 242221a6eeSDavid Howells# Parse the vmlinux section table 252221a6eeSDavid Howells# 262221a6eeSDavid Howellsopen FD, "objdump -h $vmlinux |" || die $vmlinux; 272221a6eeSDavid Howellsmy @lines = <FD>; 282221a6eeSDavid Howellsclose(FD) || die $vmlinux; 292221a6eeSDavid Howells 302221a6eeSDavid Howellsmy @sections = (); 312221a6eeSDavid Howells 322221a6eeSDavid Howellsforeach my $line (@lines) { 332221a6eeSDavid Howells chomp($line); 342221a6eeSDavid Howells if ($line =~ /\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+2[*][*]([0-9]+)/ 352221a6eeSDavid Howells ) { 362221a6eeSDavid Howells my $seg = $1; 372221a6eeSDavid Howells my $name = $2; 382221a6eeSDavid Howells my $len = Math::BigInt->new("0x" . $3); 392221a6eeSDavid Howells my $vma = Math::BigInt->new("0x" . $4); 402221a6eeSDavid Howells my $lma = Math::BigInt->new("0x" . $5); 412221a6eeSDavid Howells my $foff = Math::BigInt->new("0x" . $6); 422221a6eeSDavid Howells my $align = 2 ** $7; 432221a6eeSDavid Howells 442221a6eeSDavid Howells push @sections, { name => $name, 452221a6eeSDavid Howells vma => $vma, 462221a6eeSDavid Howells len => $len, 472221a6eeSDavid Howells foff => $foff }; 482221a6eeSDavid Howells } 492221a6eeSDavid Howells} 502221a6eeSDavid Howells 512221a6eeSDavid Howellsprint "Have $#sections sections\n"; 522221a6eeSDavid Howells 532221a6eeSDavid Howells# 542221a6eeSDavid Howells# Try and parse the vmlinux symbol table. If the vmlinux file has been created 552221a6eeSDavid Howells# from a vmlinuz file with extract-vmlinux then the symbol table will be empty. 562221a6eeSDavid Howells# 572221a6eeSDavid Howellsopen FD, "nm $vmlinux 2>/dev/null |" || die $vmlinux; 582221a6eeSDavid Howells@lines = <FD>; 592221a6eeSDavid Howellsclose(FD) || die $vmlinux; 602221a6eeSDavid Howells 612221a6eeSDavid Howellsmy %symbols = (); 622221a6eeSDavid Howellsmy $nr_symbols = 0; 632221a6eeSDavid Howells 642221a6eeSDavid Howellssub parse_symbols(@) { 652221a6eeSDavid Howells foreach my $line (@_) { 662221a6eeSDavid Howells chomp($line); 672221a6eeSDavid Howells if ($line =~ /([0-9a-f]+)\s([a-zA-Z])\s(\S+)/ 682221a6eeSDavid Howells ) { 692221a6eeSDavid Howells my $addr = "0x" . $1; 702221a6eeSDavid Howells my $type = $2; 712221a6eeSDavid Howells my $name = $3; 722221a6eeSDavid Howells 732221a6eeSDavid Howells $symbols{$name} = $addr; 742221a6eeSDavid Howells $nr_symbols++; 752221a6eeSDavid Howells } 762221a6eeSDavid Howells } 772221a6eeSDavid Howells} 782221a6eeSDavid Howellsparse_symbols(@lines); 792221a6eeSDavid Howells 802221a6eeSDavid Howellsif ($nr_symbols == 0 && $sysmap ne "") { 812221a6eeSDavid Howells print "No symbols in vmlinux, trying $sysmap\n"; 822221a6eeSDavid Howells 832221a6eeSDavid Howells open FD, "<$sysmap" || die $sysmap; 842221a6eeSDavid Howells @lines = <FD>; 852221a6eeSDavid Howells close(FD) || die $sysmap; 862221a6eeSDavid Howells parse_symbols(@lines); 872221a6eeSDavid Howells} 882221a6eeSDavid Howells 892221a6eeSDavid Howellsdie "No symbols available\n" 902221a6eeSDavid Howells if ($nr_symbols == 0); 912221a6eeSDavid Howells 922221a6eeSDavid Howellsprint "Have $nr_symbols symbols\n"; 932221a6eeSDavid Howells 942221a6eeSDavid Howellsdie "Can't find system certificate list" 952221a6eeSDavid Howells unless (exists($symbols{"__cert_list_start"}) && 968e167898SMehmet Kayaalp exists($symbols{"system_certificate_list_size"})); 972221a6eeSDavid Howells 982221a6eeSDavid Howellsmy $start = Math::BigInt->new($symbols{"__cert_list_start"}); 998e167898SMehmet Kayaalpmy $end; 1008e167898SMehmet Kayaalpmy $size; 1018e167898SMehmet Kayaalpmy $size_sym = Math::BigInt->new($symbols{"system_certificate_list_size"}); 1022221a6eeSDavid Howells 1038e167898SMehmet Kayaalpopen FD, "<$vmlinux" || die $vmlinux; 1048e167898SMehmet Kayaalpbinmode(FD); 1052221a6eeSDavid Howells 1062221a6eeSDavid Howellsmy $s = undef; 1072221a6eeSDavid Howellsforeach my $sec (@sections) { 1082221a6eeSDavid Howells my $s_name = $sec->{name}; 1092221a6eeSDavid Howells my $s_vma = $sec->{vma}; 1102221a6eeSDavid Howells my $s_len = $sec->{len}; 1112221a6eeSDavid Howells my $s_foff = $sec->{foff}; 1122221a6eeSDavid Howells my $s_vend = $s_vma + $s_len; 1132221a6eeSDavid Howells 1142221a6eeSDavid Howells next unless ($start >= $s_vma); 1152221a6eeSDavid Howells next if ($start >= $s_vend); 1162221a6eeSDavid Howells 1178e167898SMehmet Kayaalp die "Certificate list size was not found on the same section\n" 1188e167898SMehmet Kayaalp if ($size_sym < $s_vma || $size_sym > $s_vend); 1192221a6eeSDavid Howells 1202221a6eeSDavid Howells die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n" 1212221a6eeSDavid Howells if ($s); 1228e167898SMehmet Kayaalp 1238e167898SMehmet Kayaalp my $size_off = $size_sym -$s_vma + $s_foff; 1248e167898SMehmet Kayaalp my $packed; 1258e167898SMehmet Kayaalp die $vmlinux if (!defined(sysseek(FD, $size_off, SEEK_SET))); 1268e167898SMehmet Kayaalp sysread(FD, $packed, 8); 1278e167898SMehmet Kayaalp $size = unpack 'L!', $packed; 1288e167898SMehmet Kayaalp $end = $start + $size; 1298e167898SMehmet Kayaalp 1308e167898SMehmet Kayaalp printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start; 1318e167898SMehmet Kayaalp 1328e167898SMehmet Kayaalp die "Cert object partially overflows section $s_name\n" 1338e167898SMehmet Kayaalp if ($end > $s_vend); 1348e167898SMehmet Kayaalp 1352221a6eeSDavid Howells $s = $sec; 1362221a6eeSDavid Howells} 1372221a6eeSDavid Howells 1382221a6eeSDavid Howellsdie "Cert object not inside a section\n" 1392221a6eeSDavid Howells unless ($s); 1402221a6eeSDavid Howells 1412221a6eeSDavid Howellsprint "Certificate list in section ", $s->{name}, "\n"; 1422221a6eeSDavid Howells 1432221a6eeSDavid Howellsmy $foff = $start - $s->{vma} + $s->{foff}; 1442221a6eeSDavid Howells 1452221a6eeSDavid Howellsprintf "Certificate list at file offset 0x%x\n", $foff; 1462221a6eeSDavid Howells 1472221a6eeSDavid Howellsdie $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET))); 1482221a6eeSDavid Howellsmy $buf = ""; 1492221a6eeSDavid Howellsmy $len = sysread(FD, $buf, $size); 1502221a6eeSDavid Howellsdie "$vmlinux" if (!defined($len)); 1512221a6eeSDavid Howellsdie "Short read on $vmlinux\n" if ($len != $size); 1522221a6eeSDavid Howellsclose(FD) || die $vmlinux; 1532221a6eeSDavid Howells 1542221a6eeSDavid Howellsopen FD, ">$keyring" || die $keyring; 1552221a6eeSDavid Howellsbinmode(FD); 1562221a6eeSDavid Howells$len = syswrite(FD, $buf, $size); 1572221a6eeSDavid Howellsdie "$keyring" if (!defined($len)); 1582221a6eeSDavid Howellsdie "Short write on $keyring\n" if ($len != $size); 1592221a6eeSDavid Howellsclose(FD) || die $keyring; 160