1## @file
2# generate capsule
3#
4#  Copyright (c) 2007-2016, Intel Corporation. All rights reserved.<BR>
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#
11#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14
15##
16# Import Modules
17#
18import Ffs
19from GenFdsGlobalVariable import GenFdsGlobalVariable
20import StringIO
21from struct import pack
22import os
23from Common.Misc import SaveFileOnChange
24import uuid
25
26## base class for capsule data
27#
28#
29class CapsuleData:
30    ## The constructor
31    #
32    #   @param  self        The object pointer
33    def __init__(self):
34        pass
35
36    ## generate capsule data
37    #
38    #   @param  self        The object pointer
39    def GenCapsuleSubItem(self):
40        pass
41
42## FFS class for capsule data
43#
44#
45class CapsuleFfs (CapsuleData):
46    ## The constructor
47    #
48    #   @param  self        The object pointer
49    #
50    def __init__(self) :
51        self.Ffs = None
52        self.FvName = None
53
54    ## generate FFS capsule data
55    #
56    #   @param  self        The object pointer
57    #   @retval string      Generated file name
58    #
59    def GenCapsuleSubItem(self):
60        FfsFile = self.Ffs.GenFfs()
61        return FfsFile
62
63## FV class for capsule data
64#
65#
66class CapsuleFv (CapsuleData):
67    ## The constructor
68    #
69    #   @param  self        The object pointer
70    #
71    def __init__(self) :
72        self.Ffs = None
73        self.FvName = None
74        self.CapsuleName = None
75
76    ## generate FV capsule data
77    #
78    #   @param  self        The object pointer
79    #   @retval string      Generated file name
80    #
81    def GenCapsuleSubItem(self):
82        if self.FvName.find('.fv') == -1:
83            if self.FvName.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():
84                FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName.upper())
85                FdBuffer = StringIO.StringIO('')
86                FvObj.CapsuleName = self.CapsuleName
87                FvFile = FvObj.AddToBuffer(FdBuffer)
88                FvObj.CapsuleName = None
89                FdBuffer.close()
90                return FvFile
91        else:
92            FvFile = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvName)
93            return FvFile
94
95## FD class for capsule data
96#
97#
98class CapsuleFd (CapsuleData):
99    ## The constructor
100    #
101    #   @param  self        The object pointer
102    #
103    def __init__(self) :
104        self.Ffs = None
105        self.FdName = None
106        self.CapsuleName = None
107
108    ## generate FD capsule data
109    #
110    #   @param  self        The object pointer
111    #   @retval string      Generated file name
112    #
113    def GenCapsuleSubItem(self):
114        if self.FdName.find('.fd') == -1:
115            if self.FdName.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
116                FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(self.FdName.upper())
117                FdFile = FdObj.GenFd()
118                return FdFile
119        else:
120            FdFile = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FdName)
121            return FdFile
122
123## AnyFile class for capsule data
124#
125#
126class CapsuleAnyFile (CapsuleData):
127    ## The constructor
128    #
129    #   @param  self        The object pointer
130    #
131    def __init__(self) :
132        self.Ffs = None
133        self.FileName = None
134
135    ## generate AnyFile capsule data
136    #
137    #   @param  self        The object pointer
138    #   @retval string      Generated file name
139    #
140    def GenCapsuleSubItem(self):
141        return self.FileName
142
143## Afile class for capsule data
144#
145#
146class CapsuleAfile (CapsuleData):
147    ## The constructor
148    #
149    #   @param  self        The object pointer
150    #
151    def __init__(self) :
152        self.Ffs = None
153        self.FileName = None
154
155    ## generate Afile capsule data
156    #
157    #   @param  self        The object pointer
158    #   @retval string      Generated file name
159    #
160    def GenCapsuleSubItem(self):
161        return self.FileName
162
163class CapsulePayload(CapsuleData):
164    '''Generate payload file, the header is defined below:
165    #pragma pack(1)
166    typedef struct {
167        UINT32 Version;
168        EFI_GUID UpdateImageTypeId;
169        UINT8 UpdateImageIndex;
170        UINT8 reserved_bytes[3];
171        UINT32 UpdateImageSize;
172        UINT32 UpdateVendorCodeSize;
173        UINT64 UpdateHardwareInstance; //Introduced in v2
174    } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
175    '''
176    def __init__(self):
177        self.UiName = None
178        self.Version = None
179        self.ImageTypeId = None
180        self.ImageIndex = None
181        self.HardwareInstance = None
182        self.ImageFile = []
183        self.VendorCodeFile = []
184        self.Certificate_Guid = None
185        self.MonotonicCount = None
186
187    def GenCapsuleSubItem(self, AuthData=[]):
188        if not self.Version:
189            self.Version = 0x00000002
190        ImageFileSize = os.path.getsize(self.ImageFile)
191        if AuthData:
192            # the ImageFileSize need include the full authenticated info size. From first bytes of MonotonicCount to last bytes of certificate.
193            # the 32 bit is the MonotonicCount, dwLength, wRevision, wCertificateType and CertType
194            ImageFileSize += 32
195        VendorFileSize = 0
196        if self.VendorCodeFile:
197            VendorFileSize = os.path.getsize(self.VendorCodeFile)
198
199        #
200        # Fill structure
201        #
202        Guid = self.ImageTypeId.split('-')
203        Buffer = pack('=ILHHBBBBBBBBBBBBIIQ',
204                       int(self.Version,16),
205                       int(Guid[0], 16),
206                       int(Guid[1], 16),
207                       int(Guid[2], 16),
208                       int(Guid[3][-4:-2], 16),
209                       int(Guid[3][-2:], 16),
210                       int(Guid[4][-12:-10], 16),
211                       int(Guid[4][-10:-8], 16),
212                       int(Guid[4][-8:-6], 16),
213                       int(Guid[4][-6:-4], 16),
214                       int(Guid[4][-4:-2], 16),
215                       int(Guid[4][-2:], 16),
216                       int(self.ImageIndex, 16),
217                       0,
218                       0,
219                       0,
220                       ImageFileSize,
221                       VendorFileSize,
222                       int(self.HardwareInstance, 16)
223                       )
224        if AuthData:
225            Buffer += pack('QIHH', AuthData[0], AuthData[1], AuthData[2], AuthData[3])
226            Buffer += uuid.UUID(AuthData[4]).get_bytes_le()
227
228        #
229        # Append file content to the structure
230        #
231        ImageFile = open(self.ImageFile, 'rb')
232        Buffer += ImageFile.read()
233        ImageFile.close()
234        if self.VendorCodeFile:
235            VendorFile = open(self.VendorCodeFile, 'rb')
236            Buffer += VendorFile.read()
237            VendorFile.close()
238        return Buffer
239