SHARE
TWEET

MaxL

a guest Aug 1st, 2009 1,440 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2.  
  3. import sys, struct, codecs
  4.  
  5. sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
  6.  
  7. #STRING_TABLE = 0x10b60
  8. STRING_TABLE = 0x6F80
  9. storage_map = {}
  10.  
  11. FORMS = [
  12. #       ('Exit',        0xc640),
  13. #       ('Boot',        0xc6f0),
  14. #       ('Power',       0xc810),
  15. #       ('Security',0xd140),
  16. #       ('Advanced',0xd390),
  17. #       ('Main',        0x106b0),
  18. #       ('OEM',         0x10a20)
  19.         ('Setup Engine', 0x18b98)
  20. ]
  21.  
  22. def fguid(s):
  23.         a, b, c, d = struct.unpack("<IHH8s", s)
  24.         ds = ''.join('%02x'%ord(c) for c in d)
  25.         return "%08x-%04x-%04x-%s-%s"%(a,b,c,ds[:4], ds[4:])
  26.  
  27. def hexdump(s):
  28.         return ' '.join('%02x'%ord(c) for c in s)
  29.  
  30. class HiiPack(object):
  31.         def __init__(self, data, offset):
  32.                 hdr = data[offset:offset+6]
  33.                 self.length, self.type = struct.unpack("<IH", hdr)
  34.                 self.data = data[offset+6:offset+self.length]
  35.  
  36. class StringTable(HiiPack):
  37.         def __init__(self, data, offset):
  38.                 HiiPack.__init__(self, data, offset)
  39.                 self.strings = []
  40.                 hdr = self.data[:16]
  41.                 lnoff, plnoff, count, attributes = struct.unpack("<IIII", hdr)
  42.                 offsets = struct.unpack("<%dI"%count, self.data[16:16+count*4])
  43.                 self.name = self._getstring(lnoff)
  44.                 self.printablename = self._getstring(plnoff)
  45.                 for i in range(count):
  46.                         self.strings.append(self._getstring(offsets[i]))
  47.         def _getstring(self, off):
  48.                 return self.data[off-6:].decode('utf-16le').split('\0')[0]
  49.         def __getitem__(self, a):
  50.                 return self.strings.__getitem__(a)
  51.         def showinfo(self, ts=''):
  52.                 print ts+"String table:"
  53.                 print ts+" Language: %s (%s)"%(self.name, self.printablename)
  54.                 print ts+" String count: %d"%len(self.strings)
  55.  
  56. class FormOp(object):
  57.         EFI_IFR_FORM_OP            = 0x01
  58.         EFI_IFR_SUBTITLE_OP        = 0x02
  59.         EFI_IFR_TEXT_OP            = 0x03
  60.         EFI_IFR_GRAPHIC_OP         = 0x04
  61.         EFI_IFR_ONE_OF_OP          = 0x05
  62.         EFI_IFR_CHECKBOX_OP        = 0x06
  63.         EFI_IFR_NUMERIC_OP         = 0x07
  64.         EFI_IFR_PASSWORD_OP        = 0x08
  65.         EFI_IFR_ONE_OF_OPTION_OP   = 0x09 # ONEOF OPTION field
  66.         EFI_IFR_SUPPRESS_IF_OP     = 0x0A
  67.         EFI_IFR_END_FORM_OP        = 0x0B
  68.         EFI_IFR_HIDDEN_OP          = 0x0C
  69.         EFI_IFR_END_FORM_SET_OP    = 0x0D
  70.         EFI_IFR_FORM_SET_OP        = 0x0E
  71.         EFI_IFR_REF_OP             = 0x0F
  72.         EFI_IFR_END_ONE_OF_OP      = 0x10
  73.         EFI_IFR_END_OP             = EFI_IFR_END_ONE_OF_OP
  74.         EFI_IFR_INCONSISTENT_IF_OP = 0x11
  75.         EFI_IFR_EQ_ID_VAL_OP       = 0x12
  76.         EFI_IFR_EQ_ID_ID_OP        = 0x13
  77.         EFI_IFR_EQ_ID_LIST_OP      = 0x14
  78.         EFI_IFR_AND_OP             = 0x15
  79.         EFI_IFR_OR_OP              = 0x16
  80.         EFI_IFR_NOT_OP             = 0x17
  81.         EFI_IFR_END_IF_OP          = 0x18 # for endif of
  82.                                                                         # inconsistentif,
  83.                                                                         # suppressif, grayoutif
  84.         EFI_IFR_GRAYOUT_IF_OP      = 0x19
  85.         EFI_IFR_DATE_OP            = 0x1A
  86.         EFI_IFR_TIME_OP            = 0x1B
  87.         EFI_IFR_STRING_OP          = 0x1C
  88.         EFI_IFR_LABEL_OP           = 0x1D
  89.         EFI_IFR_SAVE_DEFAULTS_OP   = 0x1E
  90.         EFI_IFR_RESTORE_DEFAULTS_OP= 0x1F
  91.         EFI_IFR_BANNER_OP          = 0x20
  92.         EFI_IFR_INVENTORY_OP       = 0x21
  93.         EFI_IFR_EQ_VAR_VAL_OP      = 0x22
  94.         EFI_IFR_ORDERED_LIST_OP    = 0x23
  95.         EFI_IFR_VARSTORE_OP        = 0x24
  96.         EFI_IFR_VARSTORE_SELECT_OP = 0x25
  97.         EFI_IFR_VARSTORE_SELECT_PAIR_OP  = 0x26
  98.         EFI_IFR_VARSTORE_DEVICE_OP = 0x27
  99.         EFI_IFR_LAST_OPCODE        = EFI_IFR_VARSTORE_SELECT_PAIR_OP
  100.         EFI_IFR_OEM_OP             = 0xFE
  101.         EFI_IFR_NV_ACCESS_COMMAND  = 0xFF
  102.        
  103.         INDENTS = {
  104.                 EFI_IFR_FORM_OP            : 1,
  105.                 EFI_IFR_SUBTITLE_OP        : 0,
  106.                 EFI_IFR_TEXT_OP            : 0,
  107.                 EFI_IFR_GRAPHIC_OP         : 0,
  108.                 EFI_IFR_ONE_OF_OP          : 1,
  109.                 EFI_IFR_CHECKBOX_OP        : 0,
  110.                 EFI_IFR_NUMERIC_OP         : 0,
  111.                 EFI_IFR_PASSWORD_OP        : 0,
  112.                 EFI_IFR_ONE_OF_OPTION_OP   : 0,
  113.                 EFI_IFR_SUPPRESS_IF_OP     : 1,
  114.                 EFI_IFR_END_FORM_OP        : -1,
  115.                 EFI_IFR_HIDDEN_OP          : 0,
  116.                 EFI_IFR_END_FORM_SET_OP    : -1,
  117.                 EFI_IFR_FORM_SET_OP        : 1,
  118.                 EFI_IFR_REF_OP             : 0,
  119.                 EFI_IFR_END_OP             : -1,
  120.                 EFI_IFR_INCONSISTENT_IF_OP : 0,
  121.                 EFI_IFR_EQ_ID_VAL_OP       : 0,
  122.                 EFI_IFR_EQ_ID_ID_OP        : 0,
  123.                 EFI_IFR_EQ_ID_LIST_OP      : 0,
  124.                 EFI_IFR_AND_OP             : 0,
  125.                 EFI_IFR_OR_OP              : 0,
  126.                 EFI_IFR_NOT_OP             : 0,
  127.                 EFI_IFR_END_IF_OP          : -1,
  128.                 EFI_IFR_GRAYOUT_IF_OP      : 1,
  129.                 EFI_IFR_DATE_OP            : 0,
  130.                 EFI_IFR_TIME_OP            : 0,
  131.                 EFI_IFR_STRING_OP          : 0,
  132.                 EFI_IFR_LABEL_OP           : 0,
  133.                 EFI_IFR_SAVE_DEFAULTS_OP   : 0,
  134.                 EFI_IFR_RESTORE_DEFAULTS_OP: 0,
  135.                 EFI_IFR_BANNER_OP          : 0,
  136.                 EFI_IFR_INVENTORY_OP       : 0,
  137.                 EFI_IFR_EQ_VAR_VAL_OP      : 0,
  138.                 EFI_IFR_ORDERED_LIST_OP    : 0,
  139.                 EFI_IFR_VARSTORE_OP        : 0,
  140.                 EFI_IFR_VARSTORE_SELECT_OP : 0,
  141.                 EFI_IFR_VARSTORE_SELECT_PAIR_OP : 0,
  142.                 EFI_IFR_VARSTORE_DEVICE_OP : 0,
  143.                 EFI_IFR_LAST_OPCODE        : 0,
  144.                 EFI_IFR_OEM_OP             : 0,
  145.                 EFI_IFR_NV_ACCESS_COMMAND  : 0,
  146.         }
  147.        
  148.         def __init__(self, data):
  149.                 self.opcode, self.length = struct.unpack("<BB", data[:2])
  150.                 self.payload = data[2:self.length]
  151.                 self.indent = self.INDENTS[self.opcode]
  152.                
  153.         def showinfo(self, s, ts=''):
  154.                 if self.opcode == self.EFI_IFR_FORM_OP:
  155.                         id, title = struct.unpack("<HH", self.payload)
  156.                         print ts+"Form ID:0x%04x Name:'%s'"%(id, s[title])
  157.                 elif self.opcode == self.EFI_IFR_SUBTITLE_OP:
  158.                         print ts+"Subtitle: '%s'"%s[struct.unpack("<H", self.payload)[0]]
  159.                 elif self.opcode == self.EFI_IFR_TEXT_OP:
  160.                         if len(self.payload) != 9:
  161.                                 print ts+"BROKEN TEXT OP %r"%self.payload
  162.                         else:
  163.                                 hid, tid, t2id, flags, key=struct.unpack("<HHHBH", self.payload)
  164.                                 print ts+"Text: '%s','%s' Flags:0x%x Key:0x%x"%(s[tid],s[t2id],flags,key)
  165.                                 if s[hid] and s[hid] != ' ':
  166.                                         print ts+"\Help text: '%s'"%s[hid]
  167.                 elif self.opcode == self.EFI_IFR_FORM_SET_OP:
  168.                         guid, fsid, hid, cb, cls, subcls, nvsize = struct.unpack("<16sHHQHHH", self.payload)
  169.                         print ts+"Form Set '%s' Class %d-%d NvSize 0x%x Callback 0x%x"%(s[fsid],cls, subcls, nvsize, cb)
  170.                         print ts+"\GUID: %s"%fguid(guid)
  171.                         if s[hid] and s[hid] != ' ':
  172.                                 print ts+"\Help text: '%s'"%s[hid]
  173.                 elif self.opcode == self.EFI_IFR_END_FORM_SET_OP:
  174.                         print ts+"End Form Set"
  175.                 elif self.opcode == self.EFI_IFR_END_FORM_OP:
  176.                         print ts+"End Form"
  177.                 elif self.opcode == self.EFI_IFR_GRAYOUT_IF_OP:
  178.                         print ts+"Grayout If"
  179.                 elif self.opcode == self.EFI_IFR_SUPPRESS_IF_OP:
  180.                         print ts+"Suppress If"
  181.                 elif self.opcode == self.EFI_IFR_END_IF_OP:
  182.                         print ts+"End If",hexdump(self.payload)
  183.                 elif self.opcode == self.EFI_IFR_EQ_ID_VAL_OP:
  184.                         qid, width, val = struct.unpack("<HBH", self.payload)
  185.                         print ts+"EQ [0x%x<%d>] == 0x%x"%(qid, width, val)
  186.                 elif self.opcode == self.EFI_IFR_EQ_ID_ID_OP:
  187.                         qid, width, qid2, width2, val = struct.unpack("<HBHB", self.payload)
  188.                         print ts+"EQ [0x%x<%d>] == [0x%x.%d]"%(qid, width, qid2, width2, val)
  189.                 elif self.opcode == self.EFI_IFR_EQ_ID_LIST_OP:
  190.                         qid, width, length = struct.unpack("<HBH", self.payload[:5])
  191.                         l = struct.unpack("<%dH"%length, self.payload[5:])
  192.                         print ts+"LIST [0x%x<%d>] in (%s)"%(qid, width, ','.join(["0x%x"%i for i in l]))
  193.                 elif self.opcode == self.EFI_IFR_AND_OP:
  194.                         print ts+"AND"
  195.                 elif self.opcode == self.EFI_IFR_OR_OP:
  196.                         print ts+"OR"
  197.                 elif self.opcode == self.EFI_IFR_NOT_OP:
  198.                         print ts+"NOT"
  199.                 elif self.opcode == self.EFI_IFR_ONE_OF_OP:
  200.                         qid, width, pid, hid = struct.unpack("<HBHH", self.payload)
  201.                         storage_map[qid] = s[pid]
  202.                         print ts+"One Of [0x%x<%d>] '%s'"%(qid, width, s[pid])
  203.                         if s[hid] and s[hid] != ' ':
  204.                                 print ts+"\Help text: '%s'"%s[hid]
  205.                 elif self.opcode == self.EFI_IFR_ONE_OF_OPTION_OP:
  206.                         oid, value, flags, key = struct.unpack("<HHBH", self.payload)
  207.                         print ts+"Option '%s' = 0x%x Flags 0x%x Key 0x%x"%(s[oid], value, flags, key)
  208.                 elif self.opcode == self.EFI_IFR_END_ONE_OF_OP:
  209.                         print ts+"End One Of"
  210.                 elif self.opcode == self.EFI_IFR_LABEL_OP:
  211.                         lid = struct.unpack("<H", self.payload)[0]
  212.                         print ts+"Label ID: 0x%x"%lid
  213.                 elif self.opcode == self.EFI_IFR_REF_OP:
  214.                         fid, pid, hid, flags, key = struct.unpack("<HHHBH", self.payload)
  215.                         print ts+"Reference: '%s' Form ID 0x%x Flags 0x%x Key 0x%x"%(s[pid], fid, flags, key)
  216.                         if s[hid] and s[hid] != ' ':
  217.                                 print ts+"\Help text: '%s'"%s[hid]
  218.                 elif self.opcode in (self.EFI_IFR_TIME_OP, self.EFI_IFR_DATE_OP, self.EFI_IFR_NUMERIC_OP):
  219.                         qid, width, pid, hid, flags, key, min, max, step, default = struct.unpack("<HBHHBHHHHH", self.payload)
  220.                         t = {self.EFI_IFR_TIME_OP:'Time', self.EFI_IFR_DATE_OP:'Date', self.EFI_IFR_NUMERIC_OP:'Numeric'}[self.opcode]
  221.                         print ts+"%s: '%s' [0x%x<%d>] %d-%d Step %d Default %d Flags 0x%x"%(t, s[pid], qid, width, min, max, step, default, flags)
  222.                         if s[hid] and s[hid] != ' ':
  223.                                 print ts+"\Help text: '%s'"%s[hid]
  224.                 elif self.opcode == self.EFI_IFR_PASSWORD_OP:
  225.                         qid, width, pid, hid, flags, key, mins, maxs, encoding = struct.unpack("<HBHHBHBBH", self.payload)
  226.                         storage_map[qid] = s[pid]
  227.                         print ts+"Password: '%s' [0x%x<%d>] Flags 0x%x Key 0x%x Size %d-%d Encoding %d"%(s[pid], qid, width, flags, key, mins, maxs, encoding)
  228.                         if s[hid] and s[hid] != ' ':
  229.                                 print ts+"\Help text: '%s'"%s[hid]
  230.                 else:
  231.                         print ts+"Opcode 0x%x (%d)"%(self.opcode, self.length),hexdump(self.payload)
  232.  
  233. class Form(HiiPack):
  234.         def __init__(self, data, offset):
  235.                 HiiPack.__init__(self, data, offset)
  236.                 data = self.data
  237.                 self.opcodes = []
  238.                 while len(data):
  239.                         op = FormOp(data)
  240.                         data = data[op.length:]
  241.                         self.opcodes.append(op)
  242.                        
  243.         def showinfo(self, stringtable, ts=''):
  244.                 ind = 0
  245.                 in_if = False
  246.                 fstk = []
  247.                 for op in self.opcodes:
  248.                         if op.opcode == op.EFI_IFR_FORM_OP:
  249.                                 fstk.append(ind)
  250.                         if op.indent < 0:
  251.                                 ind += op.indent
  252.                         ots = ts+' '*ind
  253.                         if in_if and op.opcode in (op.EFI_IFR_SUPPRESS_IF_OP, op.EFI_IFR_GRAYOUT_IF_OP):
  254.                                 ots = ts+' '*(ind-1)+'+'
  255.                         try:
  256.                                 op.showinfo(stringtable, ots)
  257.                         #except:
  258.                         #       print ts+"ERROR DECODING OPCODE 0x%x LEN 0x%x"%(op.opcode, op.length)
  259.                         finally:
  260.                                 pass
  261.                         if (not in_if or op.opcode not in (op.EFI_IFR_SUPPRESS_IF_OP, op.EFI_IFR_GRAYOUT_IF_OP) ) and op.indent > 0:
  262.                                 ind += op.indent
  263.                         if op.opcode in (op.EFI_IFR_SUPPRESS_IF_OP, op.EFI_IFR_GRAYOUT_IF_OP):
  264.                                 in_if = True
  265.                         elif op.opcode == op.EFI_IFR_END_IF_OP:
  266.                                 in_if = False
  267.                         if op.opcode == op.EFI_IFR_END_FORM_OP:
  268.                                 xind = fstk.pop()
  269.                                 if xind != ind:
  270.                                         print "WARNING: Indentation mismatch"
  271.                                         ind = xind
  272.  
  273. pe = open(sys.argv[1], "rb").read()
  274.  
  275. strings = StringTable(pe, STRING_TABLE)
  276. strings.showinfo()
  277.  
  278. for fn, off in FORMS:
  279.         print
  280.         print "Reading form '%s'"%fn
  281.         f = Form(pe, off)
  282.         f.showinfo(strings, ' ')
  283.        
  284. print "Storage map:"
  285. for k in sorted(storage_map.keys()):
  286.         print " 0x%x: %s"%(k,storage_map[k])
RAW Paste Data
Want to get better at Python?
Learn to code Python in 2017
Pastebin PRO Summer Special!
Get 40% OFF on Pastebin PRO accounts!
Top