Annotation of qemu/roms/seabios/tools/acpi_extract.py, revision 1.1

1.1     ! root        1: #!/usr/bin/python
        !             2: # Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <[email protected]>
        !             3: #
        !             4: # This file may be distributed under the terms of the GNU GPLv3 license.
        !             5: 
        !             6: # Process mixed ASL/AML listing (.lst file) produced by iasl -l
        !             7: # Locate and execute ACPI_EXTRACT directives, output offset info
        !             8: # 
        !             9: # Documentation of ACPI_EXTRACT_* directive tags:
        !            10: # 
        !            11: # These directive tags output offset information from AML for BIOS runtime
        !            12: # table generation.
        !            13: # Each directive is of the form:
        !            14: # ACPI_EXTRACT_<TYPE> <array_name> <Operator> (...)
        !            15: # and causes the extractor to create an array
        !            16: # named <array_name> with offset, in the generated AML,
        !            17: # of an object of a given type in the following <Operator>.
        !            18: # 
        !            19: # A directive must fit on a single code line.
        !            20: # 
        !            21: # Object type in AML is verified, a mismatch causes a build failure.
        !            22: # 
        !            23: # Directives and operators currently supported are:
        !            24: # ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name()
        !            25: # ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name()
        !            26: # ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name()
        !            27: # ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method()
        !            28: # ACPI_EXTRACT_NAME_STRING - extract a NameString from Name()
        !            29: # ACPI_EXTRACT_PROCESSOR_START - start of Processor() block
        !            30: # ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor()
        !            31: # ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1
        !            32: #
        !            33: # ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode
        !            34: # 
        !            35: # ACPI_EXTRACT is not allowed anywhere else in code, except in comments.
        !            36: 
        !            37: import re;
        !            38: import sys;
        !            39: import fileinput;
        !            40: 
        !            41: aml = []
        !            42: asl = []
        !            43: output = {}
        !            44: debug = ""
        !            45: 
        !            46: class asl_line:
        !            47:     line = None
        !            48:     lineno = None
        !            49:     aml_offset = None
        !            50: 
        !            51: def die(diag):
        !            52:     sys.stderr.write("Error: %s; %s\n" % (diag, debug))
        !            53:     sys.exit(1)
        !            54:     
        !            55: #Store an ASL command, matching AML offset, and input line (for debugging)
        !            56: def add_asl(lineno, line):
        !            57:     l = asl_line()
        !            58:     l.line = line
        !            59:     l.lineno = lineno
        !            60:     l.aml_offset = len(aml)
        !            61:     asl.append(l)
        !            62: 
        !            63: #Store an AML byte sequence
        !            64: #Verify that offset output by iasl matches # of bytes so far
        !            65: def add_aml(offset, line):
        !            66:     o = int(offset, 16);
        !            67:     # Sanity check: offset must match size of code so far
        !            68:     if (o != len(aml)):
        !            69:         die("Offset 0x%x != 0x%x" % (o, len(aml)))
        !            70:     # Strip any trailing dots and ASCII dump after "
        !            71:     line = re.sub(r'\s*\.*\s*".*$',"", line)
        !            72:     # Strip traling whitespace
        !            73:     line = re.sub(r'\s+$',"", line)
        !            74:     # Strip leading whitespace
        !            75:     line = re.sub(r'^\s+',"", line)
        !            76:     # Split on whitespace
        !            77:     code = re.split(r'\s+', line)
        !            78:     for c in code:
        !            79:         # Require a legal hex number, two digits
        !            80:         if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))):
        !            81:             die("Unexpected octet %s" % c);
        !            82:         aml.append(int(c, 16));
        !            83: 
        !            84: # Process aml bytecode array, decoding AML
        !            85: def aml_pkglen_bytes(offset):
        !            86:     # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes.
        !            87:     pkglenbytes = aml[offset] >> 6;
        !            88:     return pkglenbytes + 1
        !            89: 
        !            90: def aml_pkglen(offset):
        !            91:     pkgstart = offset
        !            92:     pkglenbytes = aml_pkglen_bytes(offset)
        !            93:     pkglen = aml[offset] & 0x3F
        !            94:     # If multibyte, first nibble only uses bits 0-3
        !            95:     if ((pkglenbytes > 0) and (pkglen & 0x30)):
        !            96:         die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" %
        !            97:             (pkglen, pkglen))
        !            98:     offset += 1
        !            99:     pkglenbytes -= 1
        !           100:     for i in range(pkglenbytes):
        !           101:         pkglen |= aml[offset + i] << (i * 8 + 4)
        !           102:     if (len(aml) < pkgstart + pkglen):
        !           103:         die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" %
        !           104:             (pkglen, offset, len(aml)))
        !           105:     return pkglen
        !           106: 
        !           107: # Given method offset, find its NameString offset
        !           108: def aml_method_string(offset):
        !           109:     #0x14 MethodOp PkgLength NameString MethodFlags TermList
        !           110:     if (aml[offset] != 0x14):
        !           111:         die( "Method offset 0x%x: expected 0x14 actual 0x%x" %
        !           112:              (offset, aml[offset]));
        !           113:     offset += 1;
        !           114:     pkglenbytes = aml_pkglen_bytes(offset)
        !           115:     offset += pkglenbytes;
        !           116:     return offset;
        !           117: 
        !           118: # Given name offset, find its NameString offset
        !           119: def aml_name_string(offset):
        !           120:     #0x08 NameOp NameString DataRef
        !           121:     if (aml[offset] != 0x08):
        !           122:         die( "Name offset 0x%x: expected 0x08 actual 0x%x" %
        !           123:              (offset, aml[offset]));
        !           124:     return offset + 1;
        !           125: 
        !           126: # Given data offset, find dword const offset
        !           127: def aml_data_dword_const(offset):
        !           128:     #0x08 NameOp NameString DataRef
        !           129:     if (aml[offset] != 0x0C):
        !           130:         die( "Name offset 0x%x: expected 0x0C actual 0x%x" %
        !           131:              (offset, aml[offset]));
        !           132:     return offset + 1;
        !           133: 
        !           134: # Given data offset, find word const offset
        !           135: def aml_data_word_const(offset):
        !           136:     #0x08 NameOp NameString DataRef
        !           137:     if (aml[offset] != 0x0B):
        !           138:         die( "Name offset 0x%x: expected 0x0B actual 0x%x" %
        !           139:              (offset, aml[offset]));
        !           140:     return offset + 1;
        !           141: 
        !           142: # Given data offset, find byte const offset
        !           143: def aml_data_byte_const(offset):
        !           144:     #0x08 NameOp NameString DataRef
        !           145:     if (aml[offset] != 0x0A):
        !           146:         die( "Name offset 0x%x: expected 0x0A actual 0x%x" %
        !           147:              (offset, aml[offset]));
        !           148:     return offset + 1;
        !           149: 
        !           150: # Given name offset, find dword const offset
        !           151: def aml_name_dword_const(offset):
        !           152:     return aml_data_dword_const(aml_name_string(offset) + 4)
        !           153: 
        !           154: # Given name offset, find word const offset
        !           155: def aml_name_word_const(offset):
        !           156:     return aml_data_word_const(aml_name_string(offset) + 4)
        !           157: 
        !           158: # Given name offset, find byte const offset
        !           159: def aml_name_byte_const(offset):
        !           160:     return aml_data_byte_const(aml_name_string(offset) + 4)
        !           161: 
        !           162: def aml_processor_start(offset):
        !           163:     #0x5B 0x83 ProcessorOp PkgLength NameString ProcID
        !           164:     if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)):
        !           165:         die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" %
        !           166:              (offset, aml[offset], aml[offset + 1]));
        !           167:     return offset
        !           168: 
        !           169: def aml_processor_string(offset):
        !           170:     #0x5B 0x83 ProcessorOp PkgLength NameString ProcID
        !           171:     start = aml_processor_start(offset)
        !           172:     offset += 2
        !           173:     pkglenbytes = aml_pkglen_bytes(offset)
        !           174:     offset += pkglenbytes
        !           175:     return offset
        !           176: 
        !           177: def aml_processor_end(offset):
        !           178:     start = aml_processor_start(offset)
        !           179:     offset += 2
        !           180:     pkglenbytes = aml_pkglen_bytes(offset)
        !           181:     pkglen = aml_pkglen(offset)
        !           182:     return offset + pkglen
        !           183: 
        !           184: lineno = 0
        !           185: for line in fileinput.input():
        !           186:     # Strip trailing newline
        !           187:     line = line.rstrip();
        !           188:     # line number and debug string to output in case of errors
        !           189:     lineno = lineno + 1
        !           190:     debug = "input line %d: %s" % (lineno, line)
        !           191:     #ASL listing: space, then line#, then ...., then code
        !           192:     pasl = re.compile('^\s+([0-9]+)\.\.\.\.\s*')
        !           193:     m = pasl.search(line)
        !           194:     if (m):
        !           195:         add_asl(lineno, pasl.sub("", line));
        !           196:     # AML listing: offset in hex, then ...., then code
        !           197:     paml = re.compile('^([0-9A-Fa-f]+)\.\.\.\.\s*')
        !           198:     m = paml.search(line)
        !           199:     if (m):
        !           200:         add_aml(m.group(1), paml.sub("", line))
        !           201: 
        !           202: # Now go over code
        !           203: # Track AML offset of a previous non-empty ASL command
        !           204: prev_aml_offset = -1
        !           205: for i in range(len(asl)):
        !           206:     debug = "input line %d: %s" % (asl[i].lineno, asl[i].line)
        !           207: 
        !           208:     l = asl[i].line
        !           209: 
        !           210:     # skip if not an extract directive
        !           211:     a = len(re.findall(r'ACPI_EXTRACT', l))
        !           212:     if (not a):
        !           213:         # If not empty, store AML offset. Will be used for sanity checks
        !           214:         # IASL seems to put {}. at random places in the listing.
        !           215:         # Ignore any non-words for the purpose of this test.
        !           216:         m = re.search(r'\w+', l)
        !           217:         if (m):
        !           218:                 prev_aml_offset = asl[i].aml_offset
        !           219:         continue
        !           220: 
        !           221:     if (a > 1):
        !           222:         die("Expected at most one ACPI_EXTRACT per line, actual %d" % a)
        !           223: 
        !           224:     mext = re.search(r'''
        !           225:                       ^\s* # leading whitespace
        !           226:                       /\*\s* # start C comment
        !           227:                       (ACPI_EXTRACT_\w+) # directive: group(1)
        !           228:                       \s+ # whitspace separates directive from array name
        !           229:                       (\w+) # array name: group(2)
        !           230:                       \s*\*/ # end of C comment
        !           231:                       \s*$ # trailing whitespace
        !           232:                       ''', l, re.VERBOSE)
        !           233:     if (not mext):
        !           234:         die("Stray ACPI_EXTRACT in input")
        !           235: 
        !           236:     # previous command must have produced some AML,
        !           237:     # otherwise we are in a middle of a block
        !           238:     if (prev_aml_offset == asl[i].aml_offset):
        !           239:         die("ACPI_EXTRACT directive in the middle of a block")
        !           240: 
        !           241:     directive = mext.group(1)
        !           242:     array = mext.group(2)
        !           243:     offset = asl[i].aml_offset
        !           244: 
        !           245:     if (directive == "ACPI_EXTRACT_ALL_CODE"):
        !           246:         if array in output:
        !           247:             die("%s directive used more than once" % directive)
        !           248:         output[array] = aml
        !           249:         continue
        !           250:     if (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
        !           251:         offset = aml_name_dword_const(offset)
        !           252:     elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):
        !           253:         offset = aml_name_word_const(offset)
        !           254:     elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"):
        !           255:         offset = aml_name_byte_const(offset)
        !           256:     elif (directive == "ACPI_EXTRACT_NAME_STRING"):
        !           257:         offset = aml_name_string(offset)
        !           258:     elif (directive == "ACPI_EXTRACT_METHOD_STRING"):
        !           259:         offset = aml_method_string(offset)
        !           260:     elif (directive == "ACPI_EXTRACT_PROCESSOR_START"):
        !           261:         offset = aml_processor_start(offset)
        !           262:     elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"):
        !           263:         offset = aml_processor_string(offset)
        !           264:     elif (directive == "ACPI_EXTRACT_PROCESSOR_END"):
        !           265:         offset = aml_processor_end(offset)
        !           266:     else:
        !           267:         die("Unsupported directive %s" % directive)
        !           268: 
        !           269:     if array not in output:
        !           270:         output[array] = []
        !           271:     output[array].append(offset)
        !           272: 
        !           273: debug = "at end of file"
        !           274: 
        !           275: def get_value_type(maxvalue):
        !           276:     #Use type large enough to fit the table
        !           277:     if (maxvalue >= 0x10000):
        !           278:             return "int"
        !           279:     elif (maxvalue >= 0x100):
        !           280:             return "short"
        !           281:     else:
        !           282:             return "char"
        !           283: 
        !           284: # Pretty print output
        !           285: for array in output.keys():
        !           286:     otype = get_value_type(max(output[array]))
        !           287:     odata = []
        !           288:     for value in output[array]:
        !           289:         odata.append("0x%x" % value)
        !           290:     sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array))
        !           291:     sys.stdout.write(",\n".join(odata))
        !           292:     sys.stdout.write('\n};\n');

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.