#!/usr/bin/python
# -*- coding: latin-1 -*-
# INTEL CONFIDENTIAL
# Copyright 2007 Intel Corporation All Rights Reserved.
#
# The source code contained or described herein and all documents related to the
# source code (“Material”) are owned by Intel Corporation or its suppliers or
# licensors. Title to the Material remains with Intel Corporation or its
# suppliers and licensors. The Material may contain trade secrets and
# proprietary and confidential information of Intel Corporation and its
# suppliers and licensors, and is protected by worldwide copyright and trade
# secret laws and treaty provisions. No part of the Material may be used,
# copied, reproduced, modified, published, uploaded, posted, transmitted,
# distributed, or disclosed in any way without Intel’s prior express written
# permission. 
# No license under any patent, copyright, trade secret or other intellectual
# property right is granted to or conferred upon you by disclosure or delivery
# of the Materials, either expressly, by implication, inducement, estoppel or
# otherwise. Any license under such intellectual property rights must be express
# and approved by Intel in writing.
#
# Include any supplier copyright notices as supplier requires Intel to use.
#
# Include supplier trademarks or logos as supplier requires Intel to use, preceded
# by an asterisk. An asterisked footnote can be added as follows:
# *Third Party trademarks are the property of their respective owners.
#
# Unless otherwise agreed by Intel in writing, you may not remove or alter this
# notice or any other notice embedded in Materials by Intel or Intel’s suppliers
# or licensors in any way.

"""This module contains the methods to read SMBIOS data

"""
__author__ = 'Todd C Davis'
__Product__ = 'Intel_PDK'

import sys, os, os.path, popen2
from systemMgr import openSysInfo, closeSysInfo, addProperty, queryProperty
from logMgr import addLogRecord,CRITICAL,ERROR,WARNING,INFO,DEBUG
try:
    __file__
except:
    __file__ = __name__

def parseBcpId():
    sInfo = openSysInfo()
    r, w, e = popen2.popen3('nv -s -n BcpId',-1,'b')
    #elines = e.readlines()
    e.close()
    lines = r.readlines()
    r.close()
    w.close()
    for line in lines:
        parts = line.split(':',2)
        if not len(parts) == 3:
            continue
        addProperty(sInfo,'IntelBIOSID','BcpId',parts[2],{})
        break;
    closeSysInfo(sInfo)


def parseIntelBIOSID(sInfo):
    """
    BoardFamilyID.OEMID.MajorRev.MinorRev.BuildID.BuildDateTime
    Where:
    BoardFamilyID = String name for this board family.
    OEMID = Three-character OEM ID. “86B” is used for Intel EPSD.
    MajorRev = Two decimal digits
    MinorRev = Two decimal digits
    BuildID = Four decimal digits
    BuildDateTime = Build date and time in MMDDYYYYHHMM format:
        MM = Two-digit month
        DD = Two-digit day of month
        YYYY = Four-digit year
        HH = Two-digit hour using 24 hour clock
        MM = Two-digit minute
    """
    ret, value = queryProperty(sInfo,'SMBIOS','Version','',{'type':'0'})
    if value and ret == 0:
        #print "SMBIOS Version: %s" % value
        parts = value.split('.')
        if len(parts) >= 5:
             addProperty(sInfo,'IntelBIOSID','BoardFamilyID',parts[0],{})
             addProperty(sInfo,'IntelBIOSID','OEMID',parts[1],{})
             addProperty(sInfo,'IntelBIOSID','MajorRev',parts[2],{})
             addProperty(sInfo,'IntelBIOSID','MinorRev',parts[3],{})
             addProperty(sInfo,'IntelBIOSID','BuildID',parts[4],{})
             return 0
        addLogRecord(0,__file__, CRITICAL, "Invalid Intel BIOS version: %s"%value)
    return 1


"""
type 0, BIOS Information
type 1, System Information
type 2, Base Board Information
type 3, Chassis Information
type 4, Processor Information
type 10, On Board Device Information
type 11, OEM Strings
type 17, Memory Device
type 20, Memory Device Mapped Address
"""
handledRecords= ['0','1','2','3','4','10','11','17']
instanceRecords = {'4':1,'10':1,'17':1}
def handleRecord(sInfo, t, record):
    if not t in handledRecords:
        return
    attr = {}
    if instanceRecords.has_key(t):
        attr['instance'] = '%d'%instanceRecords[t]
        instanceRecords[t] = instanceRecords[t] + 1
    attr['type'] = t
    attr["info"] = record[0]
    for line in record:
        parts = line.split(':')
        if len(parts) != 2:
            continue
        n = parts[0].strip()
        v = parts[1].strip()
        if n:   #evidently some records have no value
            #print attr,
            #print "%s : %s" % (n,v)
            if v and v.find('BAD INDEX') >= 0:
                addLogRecord(0,__file__, WARNING, "SMBIOS table is invalid for record type %s (%s): %s"%(t,record[0],line))
            addProperty(sInfo,'SMBIOS',n,v,attr)

def isSameUUID(UUID):
    if sys.platform == 'win32':
        binfile = 'SMBIOSdecode'
    elif sys.platform == 'linux2':
        binfile = 'dmidecode'
    r, w, e = popen2.popen3('%s'%binfile,-1,'b')
    #elines = e.readlines()
    e.close()
    lines = r.readlines()
    r.close()
    w.close()
    for line in lines:
        if line.find(UUID) >= 0 and line.find('UUID') >= 0 :
            return 1
    return 0

def readSMBIOSrecords():
    if sys.platform == 'win32':
        binfile = 'SMBIOSdecode'
    elif sys.platform == 'linux2':
        binfile = 'dmidecode'
    r, w, e = popen2.popen3('%s'%binfile,-1,'b')
    #elines = e.readlines()
    e.close()
    lines = r.readlines()
    r.close()
    w.close()
    sInfo = openSysInfo()
    record = []
    t= ''
    for line in lines:
        if line.find('DMI table is broken') >= 0:
            addLogRecord(0,__file__, ERROR, "SMBIOS table is invalid: %s"%(line))
            break
        if line.startswith("Handle "):
            parts = line.split()
            assert parts[3] == 'type'
            t = parts[4][:-1]
        elif t:
            l = line.strip()
            if l:
                record.append(l)
            else:
                handleRecord(sInfo,t,record)
                record = []
                t = ''
    ret = parseIntelBIOSID(sInfo)
    closeSysInfo(sInfo)
    # smidriver needs loading before parseBcpId()
    # parseBcpId()
    return ret

if __name__ == '__main__':
    sys.exit(readSMBIOSrecords(""))

