OpenCorePkg/Debug/Scripts/common_uefi.py

173 lines
5.7 KiB
Python

# pylint: disable=too-many-statements,too-many-branches
"""
Common UEFI parsing and representation code.
"""
import array
class UefiMisc():
# Returns string corresponding to type value in specified charset.
@classmethod
def parse_string(cls, value, type_value, charset):
index = 0
data = array.array(type_value)
try:
while value[index] != 0:
# TODO: add more ASCII symbols?
v = value[index]
if v == 0x0A: # \n
data.append(0x5C)
data.append(0x6E)
elif v == 0x0D: # \r
data.append(0x5C)
data.append(0x72)
elif v == 0x09: # \t
data.append(0x5C)
data.append(0x74)
elif v == 0x22: # "
data.append(0x5C)
data.append(0x22)
elif v == 0x5C: # \
data.append(0x5C)
data.append(0x5C)
else:
data.append(v)
index += 1
except IndexError:
pass
return data.tobytes().decode(charset)
# Returns a UTF16 string corresponding to a (CHAR16 *) value in EFI.
@classmethod
def parse_utf16(cls, value):
return cls.parse_string(value, 'H', 'utf-16')
#
# Returns a UTF8 string corresponding to a (CHAR8 *) value in EFI.
#
@classmethod
def parse_utf8(cls, value):
return cls.parse_string(value, 'B', 'utf-8')
#
# Returns a printable EFI or RETURN status.
#
@classmethod
def parse_status(cls, value, efi):
suffix = ''
err = 0
val = int(value)
if val & 0x80000000:
err = val & ~0x80000000
elif val & 0x8000000000000000:
err = val & ~0x8000000000000000
if err != 0:
# TODO: make this a collection...
if err == 1:
suffix = 'LOAD_ERROR'
elif err == 2:
suffix = 'INVALID_PARAMETER'
elif err == 3:
suffix = 'UNSUPPORTED'
elif err == 4:
suffix = 'BAD_BUFFER_SIZE'
elif err == 5:
suffix = 'BUFFER_TOO_SMALL'
elif err == 6:
suffix = 'NOT_READY'
elif err == 7:
suffix = 'DEVICE_ERROR'
elif err == 8:
suffix = 'WRITE_PROTECTED'
elif err == 9:
suffix = 'OUT_OF_RESOURCES'
elif err == 10:
suffix = 'VOLUME_CORRUPTED'
elif err == 11:
suffix = 'VOLUME_FULL'
elif err == 12:
suffix = 'NO_MEDIA'
elif err == 13:
suffix = 'MEDIA_CHANGED'
elif err == 14:
suffix = 'NOT_FOUND'
elif err == 15:
suffix = 'ACCESS_DENIED'
elif err == 16:
suffix = 'NO_RESPONSE'
elif err == 17:
suffix = 'NO_MAPPING'
elif err == 18:
suffix = 'TIMEOUT'
elif err == 19:
suffix = 'NOT_STARTED'
elif err == 20:
suffix = 'ALREADY_STARTED'
elif err == 21:
suffix = 'ABORTED'
elif err == 22:
suffix = 'ICMP_ERROR'
elif err == 23:
suffix = 'TFTP_ERROR'
elif err == 24:
suffix = 'PROTOCOL_ERROR'
elif err == 25:
suffix = 'INCOMPATIBLE_VERSION'
elif err == 26:
suffix = 'SECURITY_VIOLATION'
elif err == 27:
suffix = 'CRC_ERROR'
elif err == 28:
suffix = 'END_OF_MEDIA'
elif err == 31:
suffix = 'END_OF_FILE'
elif err == 32:
suffix = 'INVALID_LANGUAGE'
elif err == 33:
suffix = 'COMPROMISED_DATA'
elif err == 35:
suffix = 'HTTP_ERROR'
elif efi and err == 100:
suffix = 'NETWORK_UNREACHABLE'
elif efi and err == 101:
suffix = 'HOST_UNREACHABLE'
elif efi and err == 102:
suffix = 'PROTOCOL_UNREACHABLE'
elif efi and err == 103:
suffix = 'PORT_UNREACHABLE'
elif efi and err == 104:
suffix = 'CONNECTION_FIN'
elif efi and err == 105:
suffix = 'CONNECTION_RESET'
elif efi and err == 106:
suffix = 'CONNECTION_REFUSED'
else:
if val == 0:
suffix = 'SUCCESS'
elif val == 1:
suffix = 'WARN_UNKNOWN_GLYPH'
elif val == 2:
suffix = 'WARN_DELETE_FAILURE'
elif val == 3:
suffix = 'WARN_WRITE_FAILURE'
elif val == 4:
suffix = 'WARN_BUFFER_TOO_SMALL'
elif val == 5:
suffix = 'WARN_STALE_DATA'
elif val == 6:
suffix = 'WARN_FILE_SYSTEM'
return('EFI_' if efi else 'RETURN_') + suffix if suffix != '' else hex(val)
# Returns a UTF16 string corresponding to a (CHAR16 *) value in EFI.
@classmethod
def parse_guid(cls, value):
guid = f"<{int(value['Data1']):08X}-{int(value['Data2']):04X}-{int(value['Data3']):04X}-{int(value['Data4'][0]):02X}{int(value['Data4'][1]):02X}-{int(value['Data4'][2]):02X}{int(value['Data4'][3]):02X}{int(value['Data4'][4]):02X}{int(value['Data4'][5]):02X}{int(value['Data4'][6]):02X}{int(value['Data4'][7]):02X}>"
return guid