1#!/usr/bin/python
2
3#
4#  Copyright 2014 Apple Inc. All righes reserved.
5#
6#  This program and the accompanying materials
7#  are licensed and made available under the terms and conditions of the BSD License
8#  which accompanies this distribution. The full text of the license may be found at
9#  http://opensource.org/licenses/bsd-license.php.
10#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12#
13
14import lldb
15import os
16import uuid
17import string
18import commands
19import optparse
20import shlex
21
22guid_dict = {}
23
24
25def EFI_GUID_TypeSummary (valobj,internal_dict):
26    """ Type summary for EFI GUID, print C Name if known
27    """
28    # typedef struct {
29    #   UINT32  Data1;
30    #   UINT16  Data2;
31    #   UINT16  Data3;
32    #   UINT8   Data4[8];
33    # } EFI_GUID;
34    SBError = lldb.SBError()
35
36    data1_val = valobj.GetChildMemberWithName('Data1')
37    data1 = data1_val.GetValueAsUnsigned(0)
38    data2_val = valobj.GetChildMemberWithName('Data2')
39    data2 = data2_val.GetValueAsUnsigned(0)
40    data3_val = valobj.GetChildMemberWithName('Data3')
41    data3 = data3_val.GetValueAsUnsigned(0)
42    str = "%x-%x-%x-" % (data1, data2, data3)
43
44    data4_val = valobj.GetChildMemberWithName('Data4')
45    for i in range (data4_val.num_children):
46        if i == 2:
47            str +='-'
48        str += "%02x" % data4_val.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)
49
50    return guid_dict.get (str.upper(), '')
51
52
53
54EFI_STATUS_Dict = {
55    (0x8000000000000000 |  1): "Load Error",
56    (0x8000000000000000 |  2): "Invalid Parameter",
57    (0x8000000000000000 |  3): "Unsupported",
58    (0x8000000000000000 |  4): "Bad Buffer Size",
59    (0x8000000000000000 |  5): "Buffer Too Small",
60    (0x8000000000000000 |  6): "Not Ready",
61    (0x8000000000000000 |  7): "Device Error",
62    (0x8000000000000000 |  8): "Write Protected",
63    (0x8000000000000000 |  9): "Out of Resources",
64    (0x8000000000000000 | 10): "Volume Corrupt",
65    (0x8000000000000000 | 11): "Volume Full",
66    (0x8000000000000000 | 12): "No Media",
67    (0x8000000000000000 | 13): "Media changed",
68    (0x8000000000000000 | 14): "Not Found",
69    (0x8000000000000000 | 15): "Access Denied",
70    (0x8000000000000000 | 16): "No Response",
71    (0x8000000000000000 | 17): "No mapping",
72    (0x8000000000000000 | 18): "Time out",
73    (0x8000000000000000 | 19): "Not started",
74    (0x8000000000000000 | 20): "Already started",
75    (0x8000000000000000 | 21): "Aborted",
76    (0x8000000000000000 | 22): "ICMP Error",
77    (0x8000000000000000 | 23): "TFTP Error",
78    (0x8000000000000000 | 24): "Protocol Error",
79
80                          0 : "Success",
81                          1 : "Warning Unknown Glyph",
82                          2 : "Warning Delete Failure",
83                          3 : "Warning Write Failure",
84                          4 : "Warning Buffer Too Small",
85
86    (0x80000000         |  1): "Load Error",
87    (0x80000000         |  2): "Invalid Parameter",
88    (0x80000000         |  3): "Unsupported",
89    (0x80000000         |  4): "Bad Buffer Size",
90    (0x80000000         |  5): "Buffer Too Small",
91    (0x80000000         |  6): "Not Ready",
92    (0x80000000         |  7): "Device Error",
93    (0x80000000         |  8): "Write Protected",
94    (0x80000000         |  9): "Out of Resources",
95    (0x80000000         | 10): "Volume Corrupt",
96    (0x80000000         | 11): "Volume Full",
97    (0x80000000         | 12): "No Media",
98    (0x80000000         | 13): "Media changed",
99    (0x80000000         | 14): "Not Found",
100    (0x80000000         | 15): "Access Denied",
101    (0x80000000         | 16): "No Response",
102    (0x80000000         | 17): "No mapping",
103    (0x80000000         | 18): "Time out",
104    (0x80000000         | 19): "Not started",
105    (0x80000000         | 20): "Already started",
106    (0x80000000         | 21): "Aborted",
107    (0x80000000         | 22): "ICMP Error",
108    (0x80000000         | 23): "TFTP Error",
109    (0x80000000         | 24): "Protocol Error",
110}
111
112def EFI_STATUS_TypeSummary (valobj,internal_dict):
113  #
114  # Return summary string for EFI_STATUS from dictionary
115  #
116  Status = valobj.GetValueAsUnsigned(0)
117  return EFI_STATUS_Dict.get (Status, '')
118
119
120def EFI_TPL_TypeSummary (valobj,internal_dict):
121  #
122  # Return TPL values
123  #
124
125  if valobj.TypeIsPointerType():
126    return ""
127
128  Tpl = valobj.GetValueAsUnsigned(0)
129  if   Tpl < 4:
130    Str = "%d" % Tpl
131  elif Tpl == 6:
132    Str = "TPL_DRIVER (Obsolete Concept in edk2)"
133  elif Tpl < 8:
134    Str = "TPL_APPLICATION"
135    if Tpl - 4 > 0:
136      Str += " + " + "%d" % (Tpl - 4)
137  elif Tpl < 16:
138    Str = "TPL_CALLBACK"
139    if Tpl - 8 > 0:
140      Str += " + " + "%d" % (Tpl - 4)
141  elif Tpl < 31:
142    Str = "TPL_NOTIFY"
143    if Tpl - 16 > 0:
144      Str += " + " + "%d" % (Tpl - 4)
145  elif Tpl == 31:
146    Str = "TPL_HIGH_LEVEL"
147  else:
148    Str = "Invalid TPL"
149
150  return Str
151
152
153def CHAR16_TypeSummary (valobj,internal_dict):
154  #
155  # Display EFI CHAR16 'unsigned short' as string
156  #
157  SBError = lldb.SBError()
158  Str = ''
159  if valobj.TypeIsPointerType():
160    if valobj.GetValueAsUnsigned () == 0:
161      return "NULL"
162
163    # CHAR16 *   max string size 1024
164    for i in range (1024):
165      Char = valobj.GetPointeeData(i,1).GetUnsignedInt16(SBError, 0)
166      if SBError.fail or Char == 0:
167        break
168      Str += unichr (Char)
169    Str = 'L"' + Str + '"'
170    return Str.encode ('utf-8', 'replace')
171
172  if valobj.num_children == 0:
173    # CHAR16
174    if chr (valobj.unsigned) in string.printable:
175      Str = "L'" + unichr (valobj.unsigned) + "'"
176      return Str.encode ('utf-8', 'replace')
177  else:
178    # CHAR16 []
179    for i in range (valobj.num_children):
180      Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt16(SBError, 0)
181      if Char == 0:
182        break
183      Str += unichr (Char)
184    Str = 'L"' + Str + '"'
185    return Str.encode ('utf-8', 'replace')
186
187  return Str
188
189def CHAR8_TypeSummary (valobj,internal_dict):
190  #
191  # Display EFI CHAR8 'signed char' as string
192  # unichr() is used as a junk string can produce an error message like this:
193  # UnicodeEncodeError: 'ascii' codec can't encode character u'\x90' in position 1: ordinal not in range(128)
194  #
195  SBError = lldb.SBError()
196  Str = ''
197  if valobj.TypeIsPointerType():
198    if valobj.GetValueAsUnsigned () == 0:
199      return "NULL"
200
201    # CHAR8 *   max string size 1024
202    for i in range (1024):
203      Char = valobj.GetPointeeData(i,1).GetUnsignedInt8(SBError, 0)
204      if SBError.fail or Char == 0:
205        break
206      Str += unichr (Char)
207    Str = '"' + Str + '"'
208    return Str.encode ('utf-8', 'replace')
209
210  if valobj.num_children == 0:
211    # CHAR8
212    if chr (valobj.unsigned) in string.printable:
213      Str = '"' + unichr (valobj.unsigned)  + '"'
214      return Str.encode ('utf-8', 'replace')
215  else:
216    # CHAR8 []
217    for i in range (valobj.num_children):
218      Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)
219      if Char == 0:
220        break
221      Str += unichr (Char)
222    Str = '"' + Str + '"'
223    return Str.encode ('utf-8', 'replace')
224
225  return Str
226
227device_path_dict = {
228  (0x01, 0x01): "PCI_DEVICE_PATH",
229  (0x01, 0x02): "PCCARD_DEVICE_PATH",
230  (0x01, 0x03): "MEMMAP_DEVICE_PATH",
231  (0x01, 0x04): "VENDOR_DEVICE_PATH",
232  (0x01, 0x05): "CONTROLLER_DEVICE_PATH",
233  (0x02, 0x01): "ACPI_HID_DEVICE_PATH",
234  (0x02, 0x02): "ACPI_EXTENDED_HID_DEVICE_PATH",
235  (0x02, 0x03): "ACPI_ADR_DEVICE_PATH",
236  (0x03, 0x01): "ATAPI_DEVICE_PATH",
237  (0x03, 0x12): "SATA_DEVICE_PATH",
238  (0x03, 0x02): "SCSI_DEVICE_PATH",
239  (0x03, 0x03): "FIBRECHANNEL_DEVICE_PATH",
240  (0x03, 0x04): "F1394_DEVICE_PATH",
241  (0x03, 0x05): "USB_DEVICE_PATH",
242  (0x03, 0x0f): "USB_CLASS_DEVICE_PATH",
243  (0x03, 0x10): "FW_SBP2_UNIT_LUN_DEVICE_PATH",
244  (0x03, 0x11): "DEVICE_LOGICAL_UNIT_DEVICE_PATH",
245  (0x03, 0x06): "I2O_DEVICE_PATH",
246  (0x03, 0x0b): "MAC_ADDR_DEVICE_PATH",
247  (0x03, 0x0c): "IPv4_DEVICE_PATH",
248  (0x03, 0x09): "INFINIBAND_DEVICE_PATH",
249  (0x03, 0x0e): "UART_DEVICE_PATH",
250  (0x03, 0x0a): "VENDOR_DEVICE_PATH",
251  (0x03, 0x13): "ISCSI_DEVICE_PATH",
252  (0x04, 0x01): "HARDDRIVE_DEVICE_PATH",
253  (0x04, 0x02): "CDROM_DEVICE_PATH",
254  (0x04, 0x03): "VENDOR_DEVICE_PATH",
255  (0x04, 0x04): "FILEPATH_DEVICE_PATH",
256  (0x04, 0x05): "MEDIA_PROTOCOL_DEVICE_PATH",
257  (0x05, 0x01): "BBS_BBS_DEVICE_PATH",
258  (0x7F, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",
259  (0xFF, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",
260}
261
262def EFI_DEVICE_PATH_PROTOCOL_TypeSummary (valobj,internal_dict):
263  #
264  #
265  #
266  if valobj.TypeIsPointerType():
267    # EFI_DEVICE_PATH_PROTOCOL *
268    return ""
269
270  Str = ""
271  if valobj.num_children == 3:
272    # EFI_DEVICE_PATH_PROTOCOL
273    Type    = valobj.GetChildMemberWithName('Type').unsigned
274    SubType = valobj.GetChildMemberWithName('SubType').unsigned
275    if (Type, SubType) in device_path_dict:
276      TypeStr = device_path_dict[Type, SubType]
277    else:
278      TypeStr = ""
279
280    LenLow  = valobj.GetChildMemberWithName('Length').GetChildAtIndex(0).unsigned
281    LenHigh = valobj.GetChildMemberWithName('Length').GetChildAtIndex(1).unsigned
282    Len = LenLow + (LenHigh >> 8)
283
284    Address = long ("%d" % valobj.addr)
285    if (Address == lldb.LLDB_INVALID_ADDRESS):
286      # Need to reserach this, it seems to be the nested struct case
287      ExprStr = ""
288    elif (Type & 0x7f == 0x7f):
289      ExprStr = "End Device Path" if SubType == 0xff else "End This Instance"
290    else:
291      ExprStr = "expr *(%s *)0x%08x" % (TypeStr, Address)
292
293    Str =  " {\n"
294    Str += "   (UINT8) Type    = 0x%02x // %s\n" % (Type, "END" if (Type & 0x7f == 0x7f) else "")
295    Str += "   (UINT8) SubType = 0x%02x // %s\n" % (SubType, ExprStr)
296    Str += "   (UINT8 [2]) Length = { // 0x%04x (%d) bytes\n" % (Len, Len)
297    Str += "     (UINT8) [0] = 0x%02x\n" % LenLow
298    Str += "     (UINT8) [1] = 0x%02x\n" % LenHigh
299    Str +=  "   }\n"
300    if (Type & 0x7f == 0x7f) and (SubType == 0xff):
301      pass
302    elif ExprStr != "":
303      NextNode = Address + Len
304      Str += "// Next node 'expr *(EFI_DEVICE_PATH_PROTOCOL *)0x%08x'\n" % NextNode
305
306  return Str
307
308
309
310def TypePrintFormating(debugger):
311    #
312    # Set the default print formating for EFI types in lldb.
313    # seems lldb defaults to decimal.
314    #
315    category = debugger.GetDefaultCategory()
316    FormatBool = lldb.SBTypeFormat(lldb.eFormatBoolean)
317    category.AddTypeFormat(lldb.SBTypeNameSpecifier("BOOLEAN"), FormatBool)
318
319    FormatHex  = lldb.SBTypeFormat(lldb.eFormatHex)
320    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT64"), FormatHex)
321    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT64"), FormatHex)
322    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT32"), FormatHex)
323    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT32"), FormatHex)
324    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT16"), FormatHex)
325    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT16"), FormatHex)
326    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT8"), FormatHex)
327    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT8"), FormatHex)
328    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINTN"), FormatHex)
329    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INTN"), FormatHex)
330    category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR8"), FormatHex)
331    category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR16"), FormatHex)
332
333    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_PHYSICAL_ADDRESS"), FormatHex)
334    category.AddTypeFormat(lldb.SBTypeNameSpecifier("PHYSICAL_ADDRESS"), FormatHex)
335    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_STATUS"), FormatHex)
336    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_TPL"), FormatHex)
337    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_LBA"), FormatHex)
338    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_BOOT_MODE"), FormatHex)
339    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_FV_FILETYPE"), FormatHex)
340
341    #
342    # Smart type printing for EFI
343    #
344    debugger.HandleCommand("type summary add EFI_GUID --python-function lldbefi.EFI_GUID_TypeSummary")
345    debugger.HandleCommand("type summary add EFI_STATUS --python-function lldbefi.EFI_STATUS_TypeSummary")
346    debugger.HandleCommand("type summary add EFI_TPL --python-function lldbefi.EFI_TPL_TypeSummary")
347    debugger.HandleCommand("type summary add EFI_DEVICE_PATH_PROTOCOL --python-function lldbefi.EFI_DEVICE_PATH_PROTOCOL_TypeSummary")
348
349    debugger.HandleCommand("type summary add CHAR16 --python-function lldbefi.CHAR16_TypeSummary")
350    debugger.HandleCommand('type summary add --regex "CHAR16 \[[0-9]+\]" --python-function lldbefi.CHAR16_TypeSummary')
351    debugger.HandleCommand("type summary add CHAR8 --python-function lldbefi.CHAR8_TypeSummary")
352    debugger.HandleCommand('type summary add --regex "CHAR8 \[[0-9]+\]" --python-function lldbefi.CHAR8_TypeSummary')
353
354
355gEmulatorBreakWorkaroundNeeded = True
356
357def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict):
358    #
359    # This is an lldb breakpoint script, and assumes the breakpoint is on a
360    # function with the same prototype as SecGdbScriptBreak(). The
361    # argument names are important as lldb looks them up.
362    #
363    # VOID
364    # SecGdbScriptBreak (
365    #   char                *FileName,
366    #   int                 FileNameLength,
367    #   long unsigned int   LoadAddress,
368    #   int                 AddSymbolFlag
369    #   )
370    # {
371    #   return;
372    # }
373    #
374    # When the emulator loads a PE/COFF image, it calls the stub function with
375    # the filename of the symbol file, the length of the FileName, the
376    # load address and a flag to indicate if this is a load or unload operation
377    #
378    global gEmulatorBreakWorkaroundNeeded
379
380    if gEmulatorBreakWorkaroundNeeded:
381        # turn off lldb debug prints on SIGALRM (EFI timer tick)
382        frame.thread.process.target.debugger.HandleCommand("process handle SIGALRM -n false")
383        gEmulatorBreakWorkaroundNeeded = False
384
385    # Convert C string to Python string
386    Error = lldb.SBError()
387    FileNamePtr = frame.FindVariable ("FileName").GetValueAsUnsigned()
388    FileNameLen = frame.FindVariable ("FileNameLength").GetValueAsUnsigned()
389    FileName = frame.thread.process.ReadCStringFromMemory (FileNamePtr, FileNameLen, Error)
390    if not Error.Success():
391        print "!ReadCStringFromMemory() did not find a %d byte C string at %x" % (FileNameLen, FileNamePtr)
392        # make breakpoint command contiue
393        frame.GetThread().GetProcess().Continue()
394
395    debugger = frame.thread.process.target.debugger
396    if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1:
397        LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned()
398
399        debugger.HandleCommand ("target modules add  %s" % FileName)
400        print "target modules load --slid 0x%x %s" % (LoadAddress, FileName)
401        debugger.HandleCommand ("target modules load --slide 0x%x --file %s" % (LoadAddress, FileName))
402    else:
403        target = debugger.GetSelectedTarget()
404        for SBModule in target.module_iter():
405            ModuleName  = SBModule.GetFileSpec().GetDirectory() + '/'
406            ModuleName += SBModule.GetFileSpec().GetFilename()
407            if FileName == ModuleName or FileName == SBModule.GetFileSpec().GetFilename():
408                target.ClearModuleLoadAddress (SBModule)
409                if not target.RemoveModule (SBModule):
410                    print "!lldb.target.RemoveModule (%s) FAILED" % SBModule
411
412    # make breakpoint command contiue
413    frame.thread.process.Continue()
414
415def GuidToCStructStr (guid, Name=False):
416  #
417  # Convert a 16-byte bytesarry (or bytearray compat object) to C guid string
418  # { 0xB402621F, 0xA940, 0x1E4A, { 0x86, 0x6B, 0x4D, 0xC9, 0x16, 0x2B, 0x34, 0x7C } }
419  #
420  # Name=True means lookup name in GuidNameDict and us it if you find it
421  #
422
423  if not isinstance (guid, bytearray):
424    # convert guid object to UUID, and UUID to bytearray
425    Uuid = uuid.UUID(guid)
426    guid = bytearray (Uuid.bytes_le)
427
428  return "{ 0x%02.2X%02.2X%02.2X%02.2X, 0x%02.2X%02.2X, 0x%02.2X%02.2X, { 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X } }" % \
429         (guid[3], guid[2], guid[1], guid[0], guid[5], guid[4], guid[7], guid[6], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15])
430
431def ParseGuidString(GuidStr):
432  #
433  # Error check and convert C Guid init to string
434  # ParseGuidString("49152E77-1ADA-4764-B7A2-7AFEFED95E8B")
435  # ParseGuidString("{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }")
436  #
437
438  if "{" in GuidStr                                                                                         :
439    # convert C form "{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }"
440    # to string form BA24B391-73FD-C54C-9EAF-0CA78A3546D1
441    # make a list of Hex numbers like: ['0xBA24B391', '0x73FD', '0xC54C', '0x9E', '0xAF', '0x0C', '0xA7', '0x8A', '0x35', '0x46', '0xD1']
442    Hex = ''.join(x for x in GuidStr if x not in '{,}').split()
443    Str = "%08X-%04X-%04X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X" % \
444          (int(Hex[0], 0), int(Hex[1], 0), int(Hex[2], 0), int(Hex[3], 0), int(Hex[4], 0), \
445           int(Hex[5], 0), int(Hex[6], 0), int(Hex[7], 0), int(Hex[8], 0), int(Hex[9], 0), int(Hex[10], 0))
446  elif GuidStr.count('-') == 4:
447    # validate "49152E77-1ADA-4764-B7A2-7AFEFED95E8B" form
448    Check = "%s" % str(uuid.UUID(GuidStr)).upper()
449    if GuidStr.upper() == Check:
450      Str = GuidStr.upper()
451    else:
452      Ste = ""
453  else:
454    Str = ""
455
456  return Str
457
458
459def create_guid_options():
460    usage = "usage: %prog [data]"
461    description='''lookup EFI_GUID by CName, C struct, or GUID string and print out all three.
462    '''
463    parser = optparse.OptionParser(description=description, prog='guid',usage=usage)
464    return parser
465
466def efi_guid_command(debugger, command, result, dict):
467    # Use the Shell Lexer to properly parse up command options just like a
468    # shell would
469    command_args = shlex.split(command)
470    parser = create_guid_options()
471    try:
472        (options, args) = parser.parse_args(command_args)
473        if len(args) >= 1:
474          if args[0] == "{":
475              # caller forgot to quote the string"
476              # mark arg[0] a string containing all args[n]
477              args[0] = ' '.join(args)
478          GuidStr = ParseGuidString (args[0])
479          if GuidStr == "":
480              # return Key of GuidNameDict for value args[0]
481              GuidStr = [Key for Key, Value in guid_dict.iteritems() if Value == args[0]][0]
482          GuidStr = GuidStr.upper()
483    except:
484        # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
485        # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
486        result.SetError ("option parsing failed")
487        return
488
489
490    if len(args) >= 1:
491        if GuidStr in guid_dict:
492            print "%s = %s" % (guid_dict[GuidStr], GuidStr)
493            print "%s = %s" % (guid_dict[GuidStr], GuidToCStructStr (GuidStr))
494        else:
495            print GuidStr
496    else:
497        # dump entire dictionary
498        width = max(len(v) for k,v in guid_dict.iteritems())
499        for value in sorted(guid_dict, key=guid_dict.get):
500            print '%-*s %s %s' % (width, guid_dict[value], value, GuidToCStructStr(value))
501
502    return
503
504
505#
506########## Code that runs when this script is imported into LLDB ###########
507#
508def __lldb_init_module (debugger, internal_dict):
509    # This initializer is being run from LLDB in the embedded command interpreter
510    # Make the options so we can generate the help text for the new LLDB
511    # command line command prior to registering it with LLDB below
512
513    global guid_dict
514
515    # Source Guid.xref file if we can find it
516    inputfile = os.getcwd()
517    inputfile += os.sep + os.pardir + os.sep + 'FV' + os.sep + 'Guid.xref'
518    with open(inputfile) as f:
519        for line in f:
520            data = line.split(' ')
521            if len(data) >= 2:
522                guid_dict[data[0].upper()] = data[1].strip('\n')
523
524    # init EFI specific type formaters
525    TypePrintFormating (debugger)
526
527
528    # add guid command
529    parser = create_guid_options()
530    efi_guid_command.__doc__ = parser.format_help()
531    debugger.HandleCommand('command script add -f lldbefi.efi_guid_command guid')
532
533
534    Target = debugger.GetTargetAtIndex(0)
535    if Target:
536        Breakpoint = Target.BreakpointCreateByName('SecGdbScriptBreak')
537        if Breakpoint.GetNumLocations() == 1:
538            # Set the emulator breakpoints, if we are in the emulator
539            debugger.HandleCommand("breakpoint command add -s python -F lldbefi.LoadEmulatorEfiSymbols {id}".format(id=Breakpoint.GetID()))
540            print 'Type r to run emulator. SecLldbScriptBreak armed. EFI modules should now get source level debugging in the emulator.'
541