# Copyright(c) 2017, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Intel Corporation nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
import json
import struct
from metadata import constants
from metadata import metadata
RBF_EXT = ".rbf"
GBS_EXT = ".gbs"
"""
Class GBS for operations related to GBS files
"""
class GBS:
def __init__(self, gbs_file=None):
self.guid = ''
self.metadata_len = 0
self.gbs_info = ''
self.rbf = ''
self.metadata = []
if gbs_file:
self.filename = os.path.splitext(os.path.basename(gbs_file))[0]
self.validate_gbs_file(gbs_file)
"""
classmethod to create a gbs instance from json and
rbf file. Used to create a new gbs file
@return instance of the new GBS object
"""
@classmethod
def create_gbs_from_afu_info(cls, rbf_file, afu_json):
gbs = cls()
rbf = open(rbf_file, 'rb')
rbf_content = rbf.read()
gbs.guid = constants.METADATA_GUID
gbs.metadata_len = len(afu_json)
gbs.gbs_info = afu_json
gbs.rbf = rbf_content
gbs.metadata = metadata.get_metadata(afu_json)
gbs.filename = os.path.splitext(os.path.basename(rbf_file))[0]
return gbs
"""
Set of get methods to retrieve gbs attributes
"""
def get_gbs_guid(self):
return self.guid
def get_gbs_meta_len(self):
return self.metadata_len
def get_gbs_info(self):
return self.gbs_info
def get_rbf_val(self):
return self.rbf
def get_gbs_metadata(self):
return self.metadata
"""
Function to print GBS info to the console
"""
def print_gbs_info(self):
if self.gbs_info == '':
raise Exception("No metadata in GBS file")
print(json.dumps(self.gbs_info, indent=4))
"""
Function to write a new rbf file to the filesystem
"""
def write_rbf(self, rbf_file):
if not rbf_file:
rbf_file = self.filename + RBF_EXT
with open(rbf_file, 'wb') as rbf:
rbf.write(self.rbf)
return rbf_file
"""
Function to write a new gbs file to the filesystem
"""
def write_gbs(self, gbs_file):
if not gbs_file:
gbs_file = self.filename + GBS_EXT
decoded_bytes = [c if isinstance(c, int) else ord(c)
for c in self.get_gbs_metadata()]
gbs_file_header = bytearray(decoded_bytes)
with open(gbs_file, 'wb') as gbs:
gbs.write(gbs_file_header + self.rbf)
return gbs_file
"""
Function to update gbs info in an object with input info
"""
def update_gbs_info(self, gbs_info):
self.gbs_info = gbs_info
self.metadata = metadata.get_metadata(self.gbs_info)
"""
Function to make make sure GBS file conforms to standard
and polpulate the GBS object with appropriate values
"""
def validate_gbs_file(self, gbs_file):
file = open(gbs_file, 'rb')
gbs = file.read()
if len(constants.METADATA_GUID) >= len(gbs):
raise Exception("Invalid GBS file")
self.guid = gbs[:constants.GUID_LEN]
if self.guid != constants.METADATA_GUID:
raise Exception("Unsupported GBS format")
metadata_index = constants.GUID_LEN + constants.SIZEOF_LEN_FIELD
metadata_len = struct.unpack(
"<I", gbs[constants.GUID_LEN:metadata_index])
self.metadata_len = metadata_len[0]
if self.metadata_len != 0:
self.gbs_info = json.loads(
gbs[metadata_index:(metadata_index + self.metadata_len)])
rbf_index = metadata_index + metadata_len[0]
if rbf_index == len(gbs):
raise Exception("No RBF in GBS file!")
self.rbf = gbs[rbf_index:]
self.metadata = metadata.get_metadata(self.gbs_info)