[SeaBIOS] [PATCH 2/4] acpi: add aml/asl parsing script

Michael S. Tsirkin mst at redhat.com
Wed Sep 21 14:44:29 CEST 2011


script ./src/find_ej0.pl finds all instances of
method named EJ0_ and the matching _ADR information,
and outputs the AML offset and slot mask of each.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 src/find_ej0.pl |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100755 src/find_ej0.pl

diff --git a/src/find_ej0.pl b/src/find_ej0.pl
new file mode 100755
index 0000000..37e8a8c
--- /dev/null
+++ b/src/find_ej0.pl
@@ -0,0 +1,136 @@
+#!/usr/bin/perl
+
+# Process mixed ASL/AML listing (.lst file) produced by iasl -l
+# Locate all occurences of Name _ADR followed by Method EJ0_
+# Output slot info from _ADR and offset of method name in AML
+
+use strict;
+
+my @aml = ();
+my @asl = ();
+my @asl_lineno = ();
+my @asl_to_aml_offset = ();
+my @output = ();
+
+#Store an ASL command, matching AML offset, and input line (for debugging)
+sub add_asl {
+    my $srcline = shift(@_);
+    my $line = shift(@_);
+    push @asl, $line;
+    push @asl_lineno, $.;
+    push @asl_to_aml_offset, $#aml + 1;
+}
+
+#Store an AML byte sequence
+#Verify that offset output by iasl matches # of bytes so far
+sub add_aml {
+    my $offset = shift(@_);
+    my $line = shift(@_);
+    my $o = hex($offset);
+    # Sanity check: offset must match
+    die "Offset $o != " .($#aml + 1) if ($o != $#aml + 1);
+    # Strip any traling dots and ASCII dump after "
+    $line =~ s/\s*\.*\s*".*//;
+
+    my @code = split(' ', $line);
+    foreach my $c (@code) {
+        if (not($c =~ m/^[0-9A-Fa-f][0-9A-Fa-f]$/)) {
+            die "Unexpected octet $c";
+        }
+        push @aml, hex($c);
+    }
+}
+
+# Process aml bytecode array, decoding AML
+# Given method offset, find its name offset
+sub aml_method_name {
+    my $lineno = shift(@_);
+    my $offset = shift(@_);
+    #0x14 MethodOp PkgLength NameString MethodFlags TermList
+    if ($aml[$offset] != 0x14) {
+        die "Method after input line $lineno offset $offset: " .
+            " expected 0x14 actual ". sprintf("0x%x", $aml[$offset]);
+    }
+    $offset += 1;
+    # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes.
+    my $pkglenbytes = $aml[$offset] >> 6;
+    $offset += 1 + $pkglenbytes;
+    return $offset;
+}
+
+while (<>) {
+        #Strip trailing newline
+        chomp;
+	#ASL listing: space, then line#, then ...., then code
+	if (s#^\s+([0-9]+)\.\.\.\.\s*##) {
+            add_asl($1, $_);
+	}
+        # AML listing: offset in hex, then ...., then code
+	if (s#^([0-9A-F]+)\.\.\.\.\s*##) {
+            add_aml($1, $_);
+        }
+	# Ignore everything else
+}
+
+# Now go over code, look for EJ0_ methods
+# For each such method, output slot mask from the
+# preceding _ADR line, as well as the method name offset.
+for (my $i = 0; $i <= $#asl; $i++) {
+    my $l = $asl[$i];
+    # match: Method (EJ0_,1)
+    if (not $l =~ m#^Method\s*\(\s*EJ0_\s*[,)]#) {
+        # Make sure we do not miss any EJ0_:
+        # die if EJ0_ is found anywhere else in source code
+        if ($l =~ m#EJ0_#) {
+            die "Stray EJ0_ detected at input line $asl_lineno[$i]: $asl[$i]";
+        }
+        next;
+    }
+    # EJ0_ found. Previous line must be _ADR
+    my $p = $i > 0 ? $asl[$i - 1] : "";
+    # match: Name (_ADR, 0x<address>)
+    if (not ($p =~ m#Name\s*\(\s*_ADR\s*,\s*0x([0-9A-Fa-f]+)\s*\)#)) {
+        die "_ADR not found before EJ0_ ".
+            "at input line $asl_lineno[$i]: $asl[$i]";
+    }
+    my $adr = hex($1);
+    my $slot = $adr >> 16;
+    if ($slot > 31) {
+        die "_ADR device out of range: actual $slot " .
+            "expected 0 to 31 at input line $asl_lineno[$i]: $asl[$i]";
+    }
+
+    # We have offset of EJ0_ method in code
+    # Now find EJ0_ itself
+    my $offset = $asl_to_aml_offset[$i];
+    my $ej0 = aml_method_name($asl_lineno[$i], $offset);
+    # Verify AML: name must be EJ0_:
+    if (($aml[$ej0 + 0] != ord('E')) or
+        ($aml[$ej0 + 1] != ord('J')) or
+        ($aml[$ej0 + 2] != ord('0')) or
+        ($aml[$ej0 + 3] != ord('_'))) {
+        die "AML after input line $asl_lineno[$i] offset $ej0 " .
+            "does not match EJ0_";
+    }
+
+    # OK we are done. Output slot mask and offset
+    push @output, sprintf("    {.slot_mask = 0x%x, .offset = 0x%x}",
+                          0x1 << $slot, $ej0);
+}
+
+# Pretty print output
+if ($#output < 0) {
+    die "No EJ0_ Method found!"
+}
+print <<EOF;
+static struct aml_ej0_data {
+    unsigned slot_mask;
+    unsigned offset;
+} aml_ej0_data[] = {
+EOF
+print join(",\n", @output);
+print <<EOF;
+
+};
+EOF
+
-- 
1.7.5.53.gc233e




More information about the SeaBIOS mailing list