Guest User

uefi_dump.pl

a guest
May 24th, 2015
453
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 32.18 KB | None | 0 0
  1. #!/usr/bin/perl
  2. #
  3. # Copyright (c) 2013 Nurlan Mukhanov (aka Falseclock) <[email protected]>
  4. #
  5. # Please inform me if you found error/mistakes or enhance this script.
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in all
  15. # copies or substantial portions of the Software.
  16.  
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. # SOFTWARE.
  24.  
  25. $| = 1;
  26.  
  27. use strict;
  28. use warnings;
  29. use utf8;
  30. use Encode;
  31. use Data::Dumper;
  32. use vars qw($ROM $ROM_SIZE $IFR_PACKAGE_SIG @EFI_HII_PACKAGES %EFI_HII_PACKAGE_TYPE %LANGUAGES @EFI_HII_PACKAGE_FORMS %EFI $DEFAULT_LANGUAGE @STRINGS @TABS %TYPES);
  33.  
  34. ################### !!! IMPORTANT !!! ###################
  35. $IFR_PACKAGE_SIG = '$IFRPKG!';
  36. #########################################################
  37.  
  38. $DEFAULT_LANGUAGE = 'en-US';
  39. my $file = $ARGV[0] || "Setup.rom";
  40.  
  41. &SPECIFICATION_LOAD();
  42.  
  43. #---------------------------- MAIN PROGRAMM ----------------------------#
  44.  
  45. open($ROM, "<$file ") or die "ERROR : Cannot open $file.\n";
  46. {
  47.     binmode $ROM;
  48.     undef $/;
  49.     $ROM_SIZE = -s $file;
  50. }
  51.  
  52. #--------------------------------------------------------------------
  53. # 1. Search IFR virtual package
  54. my $header_offset = &IFR_PACKAGE_SIG();
  55. print STDERR "IFR_PACKAGE_SIG not found!\nExiting programm...\n" and exit 1 if (!$header_offset);
  56.  
  57. #--------------------------------------------------------------------
  58. # 2. Search EFI_HII_PACKAGE_HEADERs
  59. @EFI_HII_PACKAGES = &EFI_HII_PACKAGES($header_offset);
  60. #print Dumper(\@EFI_HII_PACKAGES);
  61.  
  62.    
  63. #=head
  64. #--------------------------------------------------------------------
  65. # 3. Parse EFI_HII_PACKAGE_STRINGS
  66. #print "Parsing language tables..\n";
  67. %LANGUAGES = &EFI_HII_PACKAGE_STRINGS();
  68. #printf "\tFound %d languages: %s\n", scalar keys %LANGUAGES, join ', ', sort keys %LANGUAGES;
  69. @STRINGS = @{$LANGUAGES{$DEFAULT_LANGUAGE}->{'strings'}};
  70.  
  71. #print Dumper(\@STRINGS);
  72. #print Dumper(\%LANGUAGES);
  73.  
  74. =head
  75. # 3.1. Check languages length
  76. my %length;
  77. $length{$_} = scalar @{$LANGUAGES{$_}->{'strings'}}  foreach (keys %LANGUAGES);
  78.  
  79. my $warn = 0;
  80.  
  81. foreach (keys %length)
  82. {
  83.     next if $_ eq 'en-US';
  84.    
  85.     if ($length{$_} != $length{'en-US'})
  86.     {
  87.         if (!$warn)
  88.         {
  89.             printf STDERR "\tWARNING: languages array length is different, must be %d elements:\n", $length{'en-US'};
  90.             $warn = 1;
  91.         }
  92.         printf "\t\t%s: (%d)\n", $_, $length{$_} - $length{'en-US'};
  93.     }
  94. }
  95. =cut
  96. #--------------------------------------------------------------------
  97. # 4. FORM packages parsing
  98. @EFI_HII_PACKAGE_FORMS = &EFI_HII_PACKAGE_FORMS();
  99.  
  100. close($ROM);
  101.  
  102. #-----------------------------------------------------------------------#
  103. #-----------------------------------------------------------------------#
  104.  
  105. sub str2hex {
  106.     return unpack ("H*", shift);
  107. }
  108.  
  109. sub dec2bin {
  110.     return unpack("B32", pack("N", shift));
  111. }
  112.  
  113. sub bin2dec {
  114.     return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
  115. }
  116.  
  117. sub oplength {
  118.     my $data = shift;
  119.     my $length = unpack("C", $data);
  120.    
  121.     return bin2dec(substr &dec2bin($length), -7);
  122.    
  123. }
  124.  
  125. sub EFI_IFR {
  126.     my $data = shift;
  127.     my $length = length($data);
  128.    
  129.     my @opcodes;
  130.    
  131.     #printf "length: %d, hex: %s\n", length($data), join (' ', unpack("(H2)*",substr($data,0,10)));
  132.    
  133.     my $i = 0;
  134.  
  135.     while ($i < $length)
  136.     {
  137.         my %op;
  138.        
  139.         # Reading OPCODE
  140.         $op{'opcode'} = unpack("C", substr($data,$i,1));
  141.         $i++;
  142.        
  143.         # Reading length
  144.         $op{'length'} = oplength(substr($data,$i,1));
  145.         $i++;
  146.  
  147.         # Reading payload
  148.         $op{'payload'} = substr($data,$i,$op{'length'}-2);
  149.         $i += $op{'length'} -2;
  150.  
  151.         # Setting indent
  152.         #$op{'indent'} = $INDENTS{$op{'opcode'}};
  153.    
  154.         push @opcodes, \%op;
  155.        
  156. #       printf "Opcode: %02X, Length: %d\n",$op{'opcode'} , $op{'length'};
  157. #       my $www = <STDIN>;
  158.     }
  159.        
  160.     return \@opcodes;
  161. }
  162.  
  163. sub EFI_HII_PACKAGE_FORMS {
  164.     my @forms = ();
  165.    
  166.     foreach (@EFI_HII_PACKAGES)
  167.     {
  168.         my %pkg = %{$_};
  169.         my %form;
  170.         if ($_->{type} == 0x02)
  171.         {
  172.             # printf "EFI_HII_PACKAGE_FORMS offset int : %d, hex: (0x%08x)\n",$pkg{'int_offset'},$pkg{'int_offset'};
  173.             # Skeep first 4 bytes of FULLL_PACKAGE_LENGTH
  174.                    
  175.             my $FORM_PACKAGE_LENGTH = unpack('I', (data($pkg{int_offset} + 4, 3).pack("H",0))   );
  176.             my $FORM_PACKAGE_TYPE = unpack('C', (data($pkg{int_offset} + 7, 1))   );
  177.  
  178.             $form{'length'} = $FORM_PACKAGE_LENGTH;
  179.             $form{'type'} = $FORM_PACKAGE_TYPE;
  180.            
  181.             #printf "  Form length: %s, type: %s\n", $FORM_PACKAGE_LENGTH, $FORM_PACKAGE_TYPE;
  182.            
  183.             my $op_offset = $pkg{int_offset} + 8;
  184.             my $op_length = ($FORM_PACKAGE_LENGTH - 4);
  185.            
  186.             $form{'opcodes'} = &EFI_IFR(data($op_offset,$op_length));
  187.             $form{'package'} = $_;
  188.            
  189.             push @forms, \%form;
  190.         }
  191.     }
  192.    
  193.     &EFI_IFR_FORM_SET(\@forms);
  194.     #print Dumper(\@forms);
  195.    
  196.     return @forms;
  197. }
  198.  
  199. sub EFI_IFR_FORM_SET {
  200.     my $forms = shift;
  201.     my @forms = @{$forms};
  202.    
  203.     #print Dumper(\@forms);
  204.    
  205.     foreach my $form (@forms)
  206.     {
  207.         my %form = %{$form};
  208.         my @ops = @{$form{'opcodes'}};
  209.        
  210.         foreach (@ops)
  211.         {
  212.             my %op = %{$_};
  213.             &EFI_IFR_PRINT(\%op,\%{$form{'package'}});
  214.         }
  215.         print "\n";
  216.     }
  217. }
  218.  
  219. sub fguid {
  220.     my $guid = shift;
  221.    
  222.     my ($a, $b, $c, $d, $e);
  223.    
  224.     $a = unpack("H*",scalar reverse(substr($guid,0,4)));
  225.     $b = unpack("H*",scalar reverse(substr($guid,4,2)));
  226.     $c = unpack("H*",scalar reverse(substr($guid,6,2)));
  227.     $d = unpack("H*",substr($guid,8,2));
  228.     $e = unpack("H*",substr($guid,10,6));
  229.    
  230.     return sprintf("%s-%s-%s-%s-%s",$a,$b,$c,$d,$e);
  231. }
  232.  
  233. sub EFI_HII_PACKAGE_STRINGS {
  234.     my %pkg;
  235.    
  236.     foreach (@EFI_HII_PACKAGES)
  237.     {
  238.         %pkg = %{$_} and last if ($_->{type} == 0x04);
  239.     }
  240.    
  241.     my $reader= 4;  # current reading offset
  242.    
  243.     my %languages;
  244.    
  245.     while ($reader < $pkg{size}) # read until we in package
  246.     {
  247.         my $LANG_PACKAGE_LENGTH = unpack('I', (data($pkg{int_offset} + $reader, 3).pack("H",0))   );
  248.         my $LANG_PACKAGE_OFFSET = $pkg{int_offset} + $reader;
  249.        
  250.         #print $LANG_PACKAGE_LENGTH,"\n";
  251.        
  252.         if ($LANG_PACKAGE_LENGTH)
  253.         {
  254.             $reader += (3 + 1 + 42);
  255.            
  256.             my $LANG_PACKAGE_NAME = (data($pkg{int_offset} + $reader, 5)); # skip 00 - end of header
  257.            
  258.             $languages{$LANG_PACKAGE_NAME} = {'offset' => $LANG_PACKAGE_OFFSET, 'length' => $LANG_PACKAGE_LENGTH, 'name' => $LANG_PACKAGE_NAME };
  259.         }
  260.        
  261.         $reader += $LANG_PACKAGE_LENGTH - (3 + 1 + 42);
  262.     }
  263.    
  264.     foreach (keys %languages)
  265.     {
  266.         my %lang = %{$languages{$_}};
  267.        
  268.         #print "Reading language from offset: ".$lang{'offset'}."\n";
  269.         #print "Language name is: ".$lang{'name'}."\n";
  270.        
  271.         my $table = data($lang{'offset'}+46+6, $lang{'length'} - 46 - 6);
  272.    
  273.         my @table = unpack('(H2)*',$table);
  274.        
  275.         # Так как начало слова содержит флаг типа строки
  276.         # и мы не можем сделать сплит всей строки, будем читать побайтно
  277.  
  278.         my @strings;
  279.         my $position=0;
  280.         my $word = undef;
  281.         my $eof = 0;
  282.         my $last = undef;
  283.         my $skip = 0;
  284.         my $word_start = 0;
  285.         push @strings, undef;   # MEMEORY OFFSET CAN NOT BE 0
  286.        
  287.         my %EFI_HII_STRING_BLOCK = map { $_ => 1 } ('10', '11', '12', '13', '15', '16', '17', '22', '30', '31', '32', '40');
  288.        
  289.         for (my $l=0; $l < $#table; $l++)
  290.         {
  291.             my $byte = $table[$l];
  292.            
  293.             if ( exists($EFI_HII_STRING_BLOCK{$byte}) && !$word && $last ne '14')
  294.             {
  295.                 print STDERR "Unexpected EFI_HII_STRING_BLOCK -> BlockType = $byte found!\n";
  296.                 printf STDERR "String offset: %d (0x%08x)\n", $lang{'offset'} + $l, $lang{'offset'} + $l;
  297.                
  298.                 exit 1;
  299.             }
  300.            
  301.             $last = $byte and $word_start = 1 and next if ($byte eq '14');      # EFI_HII_SIBT_STRING_UCS2
  302.  
  303.             if ($byte eq '21' && !$word && !$word_start )                   # EFI_HII_SIBT_SKIP2
  304.             {
  305.                 #print "SKEEP FOUND\n";
  306.                 $skip = hex($table[$l+1]);                  # number of skips
  307.                 $l += 2;                                    # pass reading @table for next 2 bytes
  308.                
  309.                 while ($skip)
  310.                 {
  311.                     push @strings, "EFI_HII_SIBT_SKIP2-$skip";
  312.                     $skip--;
  313.                 }
  314.                 next;
  315.             }
  316.            
  317.             if ($byte eq '20' && !$word && !$word_start  )                  # EFI_HII_SIBT_DUPLICATE
  318.             {
  319.                 push @strings, $strings[$#strings];
  320.                 $l += 3;
  321.                 next;
  322.             }
  323.            
  324.             # If word end
  325.             if ($byte eq '00' && $table[$l+1] eq '00')
  326.             {
  327.                 #print $word."\n";
  328.                
  329.                 push @strings, $word;
  330.                
  331.                 $word = undef;
  332.                 $word_start = 0;
  333.                 $l++;
  334.                 next;
  335.             }
  336.            
  337.             $word .= decode('utf-16le',pack("H*",$byte).pack("H*",$table[$l+1]));
  338.            
  339.             $l++;
  340.         }
  341.         $languages{$_}->{'strings'} = \@strings;
  342.     }
  343.  
  344.     return %languages;
  345.     #print Dumper(\%languages);
  346. }
  347.  
  348. sub EFI_HII_PACKAGES {
  349.     my $offset = shift;
  350.     $offset += 8;
  351.  
  352.     my @address = ();
  353.    
  354.     while (1)
  355.     {
  356.         my $data = data($offset,8);
  357.         my $hex = unpack("H*",$data);
  358.         last if $hex !~ /^[ABCDEF0-9]{10}000000$/i;
  359.        
  360.         if ($hex =~ /^[ABCDEF0-9]{6}8001000000$/i)
  361.         {
  362.             push @address, substr ((join '', (reverse ($hex =~ m/../g))), 10);
  363.            
  364.             #my $address = substr ((join '', (reverse ($hex =~ m/../g))), 10);
  365.             #printf "$address - %s\n", hex($address);
  366.         }
  367.         $offset += 8;
  368.     }
  369.     my @pkg = ();
  370.     foreach (@address)
  371.     {
  372.         my %pkg;
  373.         $pkg{int_offset} = hex($_);
  374.         $pkg{hex_offset} = $_;
  375.         $pkg{size} = unpack("I*",data(hex($_),4));
  376.         $pkg{type} = unpack("C", data( hex($_)+7 , 1 ));
  377.         $pkg{type_name} = $EFI_HII_PACKAGE_TYPE{$pkg{type}}->{name};
  378.         $pkg{type_text} = $EFI_HII_PACKAGE_TYPE{$pkg{type}}->{text};
  379.        
  380.         push @pkg, \%pkg;
  381.     }
  382.    
  383.     return @pkg;
  384. }
  385.  
  386. sub IFR_PACKAGE_SIG {
  387.     my $i = 0;
  388.     my $offset = 0;
  389.     my $seek = undef;
  390.     my @sig = split //, $IFR_PACKAGE_SIG;
  391.    
  392.     while ($i <= $ROM_SIZE)
  393.     {
  394.         my $byte = data($i,1);
  395.         #last unless $byte;
  396.  
  397.         # If we found start of header
  398.         if ($byte eq '$')
  399.         {
  400.             $offset = $i;                                   # Store current offset
  401.             $seek = $byte;                                  # Store begining of the signature
  402.             $i++;
  403.             next;
  404.         }
  405.        
  406.         if ($offset)                                        # just to save CPU time
  407.         {
  408.             if (scalar grep $byte eq $_, @sig)
  409.             {
  410.                 $seek .= $byte if ($IFR_PACKAGE_SIG =~ $seek.$byte );
  411.                 last if ($IFR_PACKAGE_SIG eq $seek );
  412.             }
  413.             else
  414.             {
  415.                 $offset = 0;
  416.                 $seek = undef;
  417.             }
  418.         }
  419.         $i++;
  420.     }
  421.    
  422.     #printf "\nIFR_PACKAGE_SIG found at offset: %d (0x%08x)\n", ($offset, $offset) if $offset;
  423.  
  424.     return $offset;
  425. }
  426.  
  427. sub data {
  428.     my $offset = shift;
  429.     my $length = shift;
  430.     my $data;
  431.    
  432.     seek $ROM, $offset, 0;
  433.     sysread $ROM, $data, $length;
  434.    
  435.     return $data;
  436. };
  437.  
  438. sub TabSpace {
  439.     # Pushing
  440.     push @TABS, shift;
  441.    
  442.     return '    ' x (scalar @TABS - 1);
  443. }
  444.  
  445. sub TabClose {
  446.     my $length = scalar @TABS;
  447.     my $return = "";
  448.    
  449.     if ($length)
  450.     {
  451.         my $opcode = pop @TABS;
  452.    
  453.         if ($opcode == $EFI{EFI_IFR_GRAY_OUT_IF_OP})
  454.         {
  455.             $return = sprintf "\xE2\x94\x94- END IF Grayout;\n";
  456.         }
  457.         elsif ($opcode == $EFI{EFI_IFR_SUPPRESS_IF_OP})
  458.         {
  459.             $return = sprintf "\xE2\x94\x94- END IF Suppress;\n";
  460.         }
  461.         else
  462.         {
  463.             $return = "What the fuck?";
  464.         }
  465.     }
  466.     return $return;
  467. }
  468.  
  469. sub EFI_IFR_PRINT
  470. {
  471.     my $op = shift;
  472.     my $package = shift;
  473.     my $TabSpace = '';
  474.    
  475.     my %op = %{$op};
  476.     my %package = %{$package};
  477.    
  478.     if ($op{'opcode'} != $EFI{EFI_IFR_FORM_SET_OP} and scalar @TABS) {
  479.        
  480.         if ($op{'opcode'} == $EFI{EFI_IFR_SUPPRESS_IF_OP} or $op{'opcode'} == $EFI{EFI_IFR_GRAY_OUT_IF_OP})
  481.         {
  482.             $TabSpace = sprintf "|";
  483.         }
  484.         elsif ( $op{'opcode'} == $EFI{EFI_IFR_END_OP} )
  485.         {
  486.             $TabSpace = sprintf  "%s",'|    ' x (scalar @TABS - 1 );
  487.         }
  488.         else
  489.         {
  490.             $TabSpace = sprintf  "%s",'|    ' x (scalar @TABS);
  491.         }
  492.        
  493.         print $TabSpace;
  494.     }
  495.  
  496.     if    ($op{'opcode'} == $EFI{EFI_IFR_FORM_SET_OP})          {   # 0x0E
  497.         my $Guid = substr($op{'payload'},0,16);
  498.         my $FormSetTitle = unpack("S2",substr($op{'payload'},16,2));
  499.         my $Help = unpack("S2",substr($op{'payload'},18,2));
  500.         my $Flags = substr($op{'payload'},20,2);
  501.         my $ClassGuid = substr($op{'payload'},22,16);
  502.    
  503.         printf "\n\xE2\x95\x94%s\xE2\x95\x97\n","\xE2\x95\x90"x116;
  504.         printf "\x{E2}\x{95}\x{91} FormSet: '%-62sGUID: %s \xE2\x95\x91\n", ($STRINGS[$FormSetTitle]."'", fguid($Guid));
  505.         printf "\x{e2}\x{95}\x{9f}%s\x{e2}\x{95}\x{a2}\n","\x{e2}\x{94}\x{80}"x116;
  506.        
  507.  
  508.         if ($STRINGS[$Help] and $STRINGS[$Help] ne ' ')
  509.         {
  510.             printf " \\Help text: '%s'\n", $STRINGS[$Help];
  511.         }
  512.     }
  513.     elsif ($op{'opcode'} == $EFI{EFI_IFR_GUID_OP})              {   # 0x5F
  514.         my $Guid = substr($op{'payload'},0,16);
  515.         my $Data = unpack("H*", substr($op{'payload'},16));
  516.         #printf "\x{E2}\x{95}\x{91} Operation data: '%-55sGUID: %s \xE2\x95\x91\n", $Data, &fguid($Guid);
  517.     }
  518.     elsif ($op{'opcode'} == $EFI{EFI_IFR_DEFAULTSTORE_OP})      {   # 0x5C
  519.         my $DefaultId = unpack("S2", substr($op{'payload'},2,2));
  520.         my $DefaultName = unpack("S2", substr($op{'payload'},2,2));
  521.         #printf "EFI_IFR_DEFAULTSTORE_OP, length: %d, DefaultId: %s, DefaultName: %s \n",length($op{'payload'}),$DefaultId,$DefaultName ;
  522.     }
  523.     elsif ($op{'opcode'} == $EFI{EFI_IFR_VARSTORE_OP})          {   # 0x24
  524.         # typedef struct _EFI_IFR_VARSTORE {
  525.         #   EFI_IFR_OP_HEADER        Header;
  526.         #   EFI_GUID                 Guid;
  527.         #   EFI_VARSTORE_ID          VarStoreId;
  528.         #   UINT16                   Size;
  529.         #   UINT8                    Name[1];
  530.         # } EFI_IFR_VARSTORE;
  531.         #printf "EFI_IFR_VARSTORE_OP, length: %d \n",length($op{'payload'});
  532.  
  533.         my $Guid = substr($op{'payload'},0,16);
  534.         my $VarStoreId = unpack("S2", substr($op{'payload'},16,2));
  535.         my $Size = unpack("S2", substr($op{'payload'},18,2));
  536.         my $Name = substr($op{'payload'},20,12);
  537.        
  538.         printf "\x{E2}\x{95}\x{91} VarStore Id: '0x%x', Size: '%s', Name: '%s'                GUID: %s \x{E2}\x{95}\x{91}\n", $VarStoreId, $Size, $Name, &fguid($Guid);
  539.         printf "\xE2\x95\x9A%s\xE2\x95\x9D\n","\xE2\x95\x90"x116;
  540.  
  541.     }
  542.     elsif ($op{'opcode'} == $EFI{EFI_IFR_FORM_OP})              {   # 0x01
  543.         my $FormId = unpack("S2",substr($op{'payload'},0,2));
  544.         my $FormTitle = unpack("S2",substr($op{'payload'},2,2));
  545.         printf "\x{e2}\x{94}\x{8c}%s\x{e2}\x{94}\x{90}\n","\x{e2}\x{94}\x{80}"x116;
  546.         printf "\x{e2}\x{94}\x{82} Form Name: '%-86s [ ID: '0x%04x' ]\x{e2}\x{94}\x{82}\n", ($STRINGS[$FormTitle]."'", $FormId);
  547.         printf "\x{e2}\x{94}\x{94}%s\x{e2}\x{94}\x{98}\n","\x{e2}\x{94}\x{80}"x116;
  548.     }
  549.     elsif ($op{'opcode'} == $EFI{EFI_IFR_GRAY_OUT_IF_OP})       {   # 0x19
  550.         printf "%s\x{E2}\x{94}\x{8C}- Grayout IF:\n",TabSpace($op{'opcode'});
  551.     }
  552.     elsif ($op{'opcode'} == $EFI{EFI_IFR_SUPPRESS_IF_OP})       {   # 0x0A
  553.         printf "%s\xE2\x94\x8C- Suppress IF:\n",TabSpace($op{'opcode'});
  554.     }
  555.     elsif ($op{'opcode'} == $EFI{EFI_IFR_END_OP})               {   # 0x29
  556.         printf "%s",&TabClose($op{'opcode'});
  557.     }
  558.     elsif ($op{'opcode'} == $EFI{EFI_IFR_EQ_ID_VAL_OP})         {   # 0x12
  559.         my $QuestionId =  unpack("S2",substr($op{'payload'},0,2));
  560.         my $Value =  unpack("S2",substr($op{'payload'},2,2));
  561.         printf "Question [ ID: '0x%02x' ] == 0x%02x\n", $QuestionId, $Value,;
  562.     }
  563.     elsif ($op{'opcode'} == $EFI{EFI_IFR_AND_OP})               {   # 0x15
  564.         printf "AND expression\n";
  565.     }
  566.     elsif ($op{'opcode'} == $EFI{EFI_IFR_SUBTITLE_OP})          {   # 0x02
  567.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  568.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  569.  
  570.         printf "Subtitle: '%s'\n", ($STRINGS[$Prompt]) if defined $STRINGS[$Prompt] and $STRINGS[$Prompt] ne ' ';
  571.     }
  572.     elsif ($op{'opcode'} == $EFI{EFI_IFR_DEFAULT_OP})           {   # 0x5B
  573.         my $DefaultId = unpack("S2",substr($op{'payload'},0,2));
  574.         my $Type = unpack("C",substr($op{'payload'},2,1));
  575.         my $value;
  576.         if ($Type == 0) {
  577.             $value = unpack("C",substr($op{'payload'},3,1));
  578.         }
  579.         elsif ($Type == 1) {
  580.             $value = unpack("S2",substr($op{'payload'},3,2));
  581.         }
  582.         elsif ($Type == 2) {
  583.             $value = unpack("S2",substr($op{'payload'},3,2));
  584.         }
  585.         elsif ($Type == 5) {
  586.             $value = sprintf("%02d",unpack("C",substr($op{'payload'},3,1))).':'.sprintf("%02d",unpack("C",substr($op{'payload'},4,1))).':'.sprintf("%02d",unpack("C",substr($op{'payload'},5,1)));
  587.         }
  588.         elsif ($Type == 6) {
  589.             $value = unpack("S2",substr($op{'payload'},3,2)).'/'.sprintf("%02d",unpack("C",substr($op{'payload'},5,1))).'/'.sprintf("%02d",unpack("C",substr($op{'payload'},6,1)));
  590.         }
  591.         else {
  592.             $value = unpack("S*",substr($op{'payload'},3,4));
  593.         }
  594.         printf "  Default value: '%s', Type: 0x%02x\n",$value, $Type;
  595.     }
  596.     elsif ($op{'opcode'} == $EFI{EFI_IFR_TRUE_OP})              {   # 0x46
  597.         printf "EQ == TRUE\n";
  598.     }
  599.     elsif ($op{'opcode'} == $EFI{EFI_IFR_TEXT_OP})              {   # 0x03
  600.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  601.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  602.         my $TextTwo = unpack("S2",substr($op{'payload'},4,2));
  603.         my $t2 = "";
  604.         $t2 = $STRINGS[$TextTwo] if (defined $STRINGS[$TextTwo]);
  605.         printf "Text: '%-32.32sDefault: '%-32.32sHelp: '%s'\n", $STRINGS[$Prompt]."'", $t2."'", $STRINGS[$Help];
  606.     }
  607.     elsif ($op{'opcode'} == $EFI{EFI_IFR_UINT64_OP})            {   # 0x45
  608.         my $Value = $op{'payload'};
  609.         printf "VALUE = %s\n", unpack("S*",$Value);
  610.        
  611.     }
  612.     elsif ($op{'opcode'} == $EFI{EFI_IFR_EQUAL_OP})             {   # 0x2F
  613.         printf "EQUAL expression\n";
  614.     }
  615.     elsif ($op{'opcode'} == $EFI{EFI_IFR_EQ_ID_LIST_OP})        {   # 0x14
  616.  
  617.         my $QuestionId = unpack("S2", substr($op{'payload'},0,2));
  618.         my $ListLength = unpack("S2", substr($op{'payload'},2,2));
  619.         my @ValueList = unpack("(S4)*", substr($op{'payload'},4));
  620.         @ValueList = map {sprintf "'0x%02x'", $_ } @ValueList;
  621.        
  622.         printf "LIST [ ID: '0x%02x' ] in (%s)\n",$QuestionId, join ",", @ValueList;
  623.     }
  624.     elsif ($op{'opcode'} == $EFI{EFI_IFR_OR_OP})                {   # 0x16
  625.         printf "OR expression\n";
  626.     }
  627.     elsif ($op{'opcode'} == $EFI{EFI_IFR_NOT_OP})               {   # 0x17
  628.         printf "NOT expression \n";
  629.     }
  630.     elsif ($op{'opcode'} == $EFI{EFI_IFR_TIME_OP})              {# 0x1b
  631.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  632.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  633.         my $QuestionId = unpack("S2",substr($op{'payload'},4,2));
  634.         my $VarStoreId = unpack("S2",substr($op{'payload'},8,2));
  635.        
  636.         #my $VarName = unpack("S2",substr($op{'payload'},8,1));
  637.         #my $VarOffset = unpack("S2",substr($op{'payload'},9,1));
  638.         #my $Flags = unpack("S2",substr($op{'payload'},9,1));
  639.    
  640.         printf "Time: '%s' [ QuestionId: '0x%02x', VarStore: '0x%02x', Help: '%s' ]\n", $STRINGS[$Prompt],$QuestionId,$VarStoreId,$STRINGS[$Help] ;    
  641.     }
  642.     elsif ($op{'opcode'} == $EFI{EFI_IFR_DATE_OP})              {# 0x1A
  643.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  644.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  645.         my $QuestionId = unpack("S2",substr($op{'payload'},4,2));
  646.         my $VarStoreId = unpack("S2",substr($op{'payload'},8,2));
  647.        
  648.         #my $VarName = unpack("S2",substr($op{'payload'},8,1));
  649.         #my $VarOffset = unpack("S2",substr($op{'payload'},9,1));
  650.         #my $Flags = unpack("S2",substr($op{'payload'},9,1));
  651.    
  652.         printf "Date: '%s' [ QuestionId: '0x%02x', VarStore: '0x%02x', Help: '%s' ]\n", $STRINGS[$Prompt],$QuestionId,$VarStoreId,$STRINGS[$Help] ;
  653.     }
  654.     elsif ($op{'opcode'} == $EFI{EFI_IFR_NUMERIC_OP})           {# 0x07
  655.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  656.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  657.         my $QuestionId = unpack("S2",substr($op{'payload'},4,2));
  658.         my $VarStoreId = unpack("S2",substr($op{'payload'},8,2));
  659.         #my $VarStoreInfo = unpack("C",substr($op{'payload'},10,1));
  660.  
  661.         my $Type = unpack("C",substr($op{'payload'},11,1));
  662.         my $MinValue = unpack("C",substr($op{'payload'},12,1));
  663.         my $MaxValue = unpack("C",substr($op{'payload'},13,1));
  664.         my $Step = unpack("C",substr($op{'payload'},14,1));
  665.  
  666.         printf "Number question: Prompt: %s, Help: %s\n",($STRINGS[$Prompt], $STRINGS[$Help]) if $Prompt;
  667.         printf "%s \x{E2}\x{94}\x{94}- [ QuestionId: '0x%02x', VarStore: '0x%02x' , Type: '%02x', MinValue: '%d', MaxValue: '%d', Step: '%d' ]\n",($TabSpace,$QuestionId, $VarStoreId, $Type,$MinValue, $MaxValue, $Step) if $Prompt;;
  668.     }
  669.     elsif ($op{'opcode'} == $EFI{EFI_IFR_REF_OP})               {# 0x0F
  670.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  671.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  672.         my $QuestionId = unpack("S2",substr($op{'payload'},4,2));
  673.         my $VarStoreId = unpack("S2",substr($op{'payload'},8,2));
  674.        
  675.         my $FormId = unpack("S2>*!",substr($op{'payload'},11,4));
  676.        
  677.         printf "Reference: '%s' [ FormID: '0x%04x', QuestionId: '0x%02x', VarStore: '0x%02x' ]\n", $STRINGS[$Prompt], $FormId, $QuestionId, $VarStoreId;
  678.     }
  679.     elsif ($op{'opcode'} == $EFI{EFI_IFR_ACTION_OP})            {# 0x0C
  680.         my $Prompt = unpack("S2",substr($op{'payload'},0,2));
  681.         my $Help = unpack("S2",substr($op{'payload'},2,2));
  682.         my $QuestionId = unpack("S2",substr($op{'payload'},4,2));
  683.         my $VarStoreId = unpack("S2",substr($op{'payload'},8,2));
  684.         #my $VarStoreInfo = unpack("C",substr($op{'payload'},8,1));
  685.        
  686.         printf "Action: '%-32.32s [ QuestionId: '0x%02x', VarStore: '0x%02x', Help: %s ] \n", ($STRINGS[$Prompt]."'", $QuestionId,$VarStoreId, $STRINGS[$Help]);
  687.         #printf "%s \x{E2}\x{94}\x{94}- \n", ($TabSpace if $STRINGS[$Prompt];
  688.     }
  689.     elsif ($op{'opcode'} == $EFI{EFI_IFR_PASSWORD_OP})          {# 0x08
  690.         my $Prompt = unpack("S2", substr($op{'payload'},0,2));
  691.         my $Help    = unpack("S2", substr($op{'payload'},2,2));
  692.         my $VarStoreId = unpack("S2", substr($op{'payload'},8,2));
  693.         printf "Password: %-32.32s [ VarStore: '0x%02x', Help: '%s']\n", ($STRINGS[$Prompt], $VarStoreId, $STRINGS[$Help]);
  694.     }
  695.     elsif ($op{'opcode'} == $EFI{EFI_IFR_ONE_OF_OP}) {          # 0x05
  696.         my $Prompt = unpack("S2", substr($op{'payload'},0,2));
  697.         my $Help    = unpack("S2", substr($op{'payload'},2,2));
  698.         my $QuestionId = unpack("S2", substr($op{'payload'},4,2));
  699.         my $VarStoreId = unpack("S2", substr($op{'payload'},8,2));
  700. #       my $VarOffset    = unpack("S2", substr($op{'payload'},4,2));
  701.        
  702.         printf "Select option: '%-32.32s[ VarStore: '0x%02x', QuestionId: '0x%02x',   Help: '%s']\n", ($STRINGS[$Prompt]."'", $VarStoreId, $QuestionId, (defined $STRINGS[$Help] ? $STRINGS[$Help] : '' ));
  703.     }
  704.     elsif ($op{'opcode'} == $EFI{EFI_IFR_ONE_OF_OPTION_OP}) {   # 0x09
  705.         my $Option  = unpack("S2", substr($op{'payload'},0,2));
  706.         my $Flags   = str2hex(substr($op{'payload'},2,1));
  707.         my $Type    = unpack("C", substr($op{'payload'},3,1));
  708.         my $Value   = unpack("C*", substr($op{'payload'},4,8));
  709.  
  710. #           oid, value, flags, key = struct.unpack("<HHBH", self.payload)
  711. #           print ts+"Option '%s' = 0x%x Flags 0x%x Key 0x%x"%(s[oid], value, flags, key)
  712.        
  713.         printf "  Option: '%-37.37s[ Value: '%s'   Default: '%-6s    Type: '%-6.6s ]\n", ($STRINGS[$Option]."'", $Value, ($Flags eq '10' ? 'true' : 'false')."'", $TYPES{$Type}."'");
  714.  
  715.     }
  716.     else {
  717.         printf "--> UNKNOWN OPCODE: %02X, length: %d\n", $op{'opcode'}, $op{'length'};
  718.         exit 1;
  719.     }
  720. }
  721.  
  722. sub SPECIFICATION_LOAD
  723. {
  724.     $EFI{EFI_IFR_FORM_OP}                 = 0x01;
  725.     $EFI{EFI_IFR_SUBTITLE_OP}             = 0x02;
  726.     $EFI{EFI_IFR_TEXT_OP}                 = 0x03;
  727.     $EFI{EFI_IFR_IMAGE_OP}                = 0x04;
  728.     $EFI{EFI_IFR_ONE_OF_OP}               = 0x05;
  729.     $EFI{EFI_IFR_CHECKBOX_OP}             = 0x06;
  730.     $EFI{EFI_IFR_NUMERIC_OP}              = 0x07;
  731.     $EFI{EFI_IFR_PASSWORD_OP}             = 0x08;
  732.     $EFI{EFI_IFR_ONE_OF_OPTION_OP}        = 0x09;
  733.     $EFI{EFI_IFR_SUPPRESS_IF_OP}          = 0x0A;
  734.     $EFI{EFI_IFR_LOCKED_OP}               = 0x0B;
  735.     $EFI{EFI_IFR_ACTION_OP}               = 0x0C;
  736.     $EFI{EFI_IFR_RESET_BUTTON_OP}         = 0x0D;
  737.     $EFI{EFI_IFR_FORM_SET_OP}             = 0x0E;
  738.     $EFI{EFI_IFR_REF_OP}                  = 0x0F;
  739.     $EFI{EFI_IFR_NO_SUBMIT_IF_OP}         = 0x10;
  740.     $EFI{EFI_IFR_INCONSISTENT_IF_OP}      = 0x11;
  741.     $EFI{EFI_IFR_EQ_ID_VAL_OP}            = 0x12;
  742.     $EFI{EFI_IFR_EQ_ID_ID_OP}             = 0x13;
  743.     $EFI{EFI_IFR_EQ_ID_LIST_OP}           = 0x14;
  744.     $EFI{EFI_IFR_AND_OP}                  = 0x15;
  745.     $EFI{EFI_IFR_OR_OP}                   = 0x16;
  746.     $EFI{EFI_IFR_NOT_OP}                  = 0x17;
  747.     $EFI{EFI_IFR_RULE_OP}                 = 0x18;
  748.     $EFI{EFI_IFR_GRAY_OUT_IF_OP}          = 0x19;
  749.     $EFI{EFI_IFR_DATE_OP}                 = 0x1A;
  750.     $EFI{EFI_IFR_TIME_OP}                 = 0x1B;
  751.     $EFI{EFI_IFR_STRING_OP}               = 0x1C;
  752.     $EFI{EFI_IFR_REFRESH_OP}              = 0x1D;
  753.     $EFI{EFI_IFR_DISABLE_IF_OP}           = 0x1E;
  754.     $EFI{EFI_IFR_ANIMATION_OP}            = 0x1F;
  755.     $EFI{EFI_IFR_TO_LOWER_OP}             = 0x20;
  756.     $EFI{EFI_IFR_TO_UPPER_OP}             = 0x21;
  757.     $EFI{EFI_IFR_MAP_OP}                  = 0x22;
  758.     $EFI{EFI_IFR_ORDERED_LIST_OP}         = 0x23;
  759.     $EFI{EFI_IFR_VARSTORE_OP}             = 0x24;
  760.     $EFI{EFI_IFR_VARSTORE_NAME_VALUE_OP}  = 0x25;
  761.     $EFI{EFI_IFR_VARSTORE_EFI_OP}         = 0x26;
  762.     $EFI{EFI_IFR_VARSTORE_DEVICE_OP}      = 0x27;
  763.     $EFI{EFI_IFR_VERSION_OP}              = 0x28;
  764.     $EFI{EFI_IFR_END_OP}                  = 0x29;
  765.     $EFI{EFI_IFR_MATCH_OP}                = 0x2A;
  766.     $EFI{EFI_IFR_GET_OP}                  = 0x2B;
  767.     $EFI{EFI_IFR_SET_OP}                  = 0x2C;
  768.     $EFI{EFI_IFR_READ_OP}                 = 0x2D;
  769.     $EFI{EFI_IFR_WRITE_OP}                = 0x2E;
  770.     $EFI{EFI_IFR_EQUAL_OP}                = 0x2F;
  771.     $EFI{EFI_IFR_NOT_EQUAL_OP}            = 0x30;
  772.     $EFI{EFI_IFR_GREATER_THAN_OP}         = 0x31;
  773.     $EFI{EFI_IFR_GREATER_EQUAL_OP}        = 0x32;
  774.     $EFI{EFI_IFR_LESS_THAN_OP}            = 0x33;
  775.     $EFI{EFI_IFR_LESS_EQUAL_OP}           = 0x34;
  776.     $EFI{EFI_IFR_BITWISE_AND_OP}          = 0x35;
  777.     $EFI{EFI_IFR_BITWISE_OR_OP}           = 0x36;
  778.     $EFI{EFI_IFR_BITWISE_NOT_OP}          = 0x37;
  779.     $EFI{EFI_IFR_SHIFT_LEFT_OP}           = 0x38;
  780.     $EFI{EFI_IFR_SHIFT_RIGHT_OP}          = 0x39;
  781.     $EFI{EFI_IFR_ADD_OP}                  = 0x3A;
  782.     $EFI{EFI_IFR_SUBTRACT_OP}             = 0x3B;
  783.     $EFI{EFI_IFR_MULTIPLY_OP}             = 0x3C;
  784.     $EFI{EFI_IFR_DIVIDE_OP}               = 0x3D;
  785.     $EFI{EFI_IFR_MODULO_OP}               = 0x3E;
  786.     $EFI{EFI_IFR_RULE_REF_OP}             = 0x3F;
  787.     $EFI{EFI_IFR_QUESTION_REF1_OP}        = 0x40;
  788.     $EFI{EFI_IFR_QUESTION_REF2_OP}        = 0x41;
  789.     $EFI{EFI_IFR_UINT8_OP}                = 0x42;
  790.     $EFI{EFI_IFR_UINT16_OP}               = 0x43;
  791.     $EFI{EFI_IFR_UINT32_OP}               = 0x44;
  792.     $EFI{EFI_IFR_UINT64_OP}               = 0x45;
  793.     $EFI{EFI_IFR_TRUE_OP}                 = 0x46;
  794.     $EFI{EFI_IFR_FALSE_OP}                = 0x47;
  795.     $EFI{EFI_IFR_TO_UINT_OP}              = 0x48;
  796.     $EFI{EFI_IFR_TO_STRING_OP}            = 0x49;
  797.     $EFI{EFI_IFR_TO_BOOLEAN_OP}           = 0x4A;
  798.     $EFI{EFI_IFR_MID_OP}                  = 0x4B;
  799.     $EFI{EFI_IFR_FIND_OP}                 = 0x4C;
  800.     $EFI{EFI_IFR_TOKEN_OP}                = 0x4D;
  801.     $EFI{EFI_IFR_STRING_REF1_OP}          = 0x4E;
  802.     $EFI{EFI_IFR_STRING_REF2_OP}          = 0x4F;
  803.     $EFI{EFI_IFR_CONDITIONAL_OP}          = 0x50;
  804.     $EFI{EFI_IFR_QUESTION_REF3_OP}        = 0x51;
  805.     $EFI{EFI_IFR_ZERO_OP}                 = 0x52;
  806.     $EFI{EFI_IFR_ONE_OP}                  = 0x53;
  807.     $EFI{EFI_IFR_ONES_OP}                 = 0x54;
  808.     $EFI{EFI_IFR_UNDEFINED_OP}            = 0x55;
  809.     $EFI{EFI_IFR_LENGTH_OP}               = 0x56;
  810.     $EFI{EFI_IFR_DUP_OP}                  = 0x57;
  811.     $EFI{EFI_IFR_THIS_OP}                 = 0x58;
  812.     $EFI{EFI_IFR_SPAN_OP}                 = 0x59;
  813.     $EFI{EFI_IFR_VALUE_OP}                = 0x5A;
  814.     $EFI{EFI_IFR_DEFAULT_OP}              = 0x5B;
  815.     $EFI{EFI_IFR_DEFAULTSTORE_OP}         = 0x5C;
  816.     $EFI{EFI_IFR_FORM_MAP_OP}             = 0x5D;
  817.     $EFI{EFI_IFR_CATENATE_OP}             = 0x5E;
  818.     $EFI{EFI_IFR_GUID_OP}                 = 0x5F;
  819.     $EFI{EFI_IFR_SECURITY_OP}             = 0x60;
  820.  
  821.     %EFI_HII_PACKAGE_TYPE =
  822.     (
  823.         0x00    => { name => 'EFI_HII_PACKAGE_TYPE_ALL'             , text => 'Pseudo-package type' },
  824.         0x01    => { name => 'EFI_HII_PACKAGE_TYPE_GUID'            , text => 'Package type where the format of the data is specified using a GUID immediately following the package header' },
  825.         0x02    => { name => 'EFI_HII_PACKAGE_FORMS'                , text => 'Forms package' },
  826.         0x04    => { name => 'EFI_HII_PACKAGE_STRINGS'              , text => 'Strings package' },
  827.         0x05    => { name => 'EFI_HII_PACKAGE_FONTS'                , text => 'Fonts package' },
  828.         0x06    => { name => 'EFI_HII_PACKAGE_IMAGES'               , text => 'Images package' },
  829.         0x07    => { name => 'EFI_HII_PACKAGE_SIMPLE_FONTS'         , text => 'Simplified (8x19, 16x19) Fonts package' },
  830.         0x08    => { name => 'EFI_HII_PACKAGE_DEVICE_PATH'          , text => 'Binary-encoded device path' },
  831.         0x09    => { name => 'EFI_HII_PACKAGE_KEYBOARD_LAYOUT'      , text => 'Used to mark the end of a package list' },
  832.         0x0A    => { name => 'EFI_HII_PACKAGE_ANIMATIONS'           , text => 'Animations package' },
  833.         0xDF    => { name => 'EFI_HII_PACKAGE_END'                  , text => 'Package types reserved for use by platform firmware implementations' },
  834.         0xE0    => { name => 'EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN'    , text => 'Package types reserved for use by platform firmware implementations' },
  835.     );
  836.  
  837. %TYPES =
  838. (
  839.     0x00 => 'int8',
  840.     0x01 => 'int16',
  841.     0x02 => 'int32',
  842.     0x03 => 'int64',
  843.     0x04 => 'bool',
  844.     0x05 => 'time',
  845.     0x06 => 'date',
  846.     0x07 => 'string',
  847.     0x08 => 'other',
  848. );
  849. }
Advertisement
Add Comment
Please, Sign In to add comment