Example #1
0
    def _InitializeInf (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1'):
        #
        # Create FV inf file
        #
        self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
                                   self.UiFvName + '.inf')
        self.FvInfFile = []

        #
        # Add [Options]
        #
        self.FvInfFile.append("[options]" + TAB_LINE_BREAK)
        if BaseAddress is not None:
            self.FvInfFile.append("EFI_BASE_ADDRESS = " + \
                                       BaseAddress          + \
                                       TAB_LINE_BREAK)

        if BlockSize is not None:
            self.FvInfFile.append("EFI_BLOCK_SIZE = " + \
                                      '0x%X' %BlockSize    + \
                                      TAB_LINE_BREAK)
            if BlockNum is not None:
                self.FvInfFile.append("EFI_NUM_BLOCKS   = "  + \
                                      ' 0x%X' %BlockNum    + \
                                      TAB_LINE_BREAK)
        else:
            if self.BlockSizeList == []:
                if not self._GetBlockSize():
                    #set default block size is 1
                    self.FvInfFile.append("EFI_BLOCK_SIZE  = 0x1" + TAB_LINE_BREAK)

            for BlockSize in self.BlockSizeList:
                if BlockSize[0] is not None:
                    self.FvInfFile.append("EFI_BLOCK_SIZE  = "  + \
                                          '0x%X' %BlockSize[0]    + \
                                          TAB_LINE_BREAK)

                if BlockSize[1] is not None:
                    self.FvInfFile.append("EFI_NUM_BLOCKS   = "  + \
                                          ' 0x%X' %BlockSize[1]    + \
                                          TAB_LINE_BREAK)

        if self.BsBaseAddress is not None:
            self.FvInfFile.append('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
                                       '0x%X' %self.BsBaseAddress)
        if self.RtBaseAddress is not None:
            self.FvInfFile.append('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
                                      '0x%X' %self.RtBaseAddress)
        #
        # Add attribute
        #
        self.FvInfFile.append("[attributes]" + TAB_LINE_BREAK)

        self.FvInfFile.append("EFI_ERASE_POLARITY   = "       + \
                                          ' %s' %ErasePloarity    + \
                                          TAB_LINE_BREAK)
        if not (self.FvAttributeDict is None):
            for FvAttribute in self.FvAttributeDict.keys():
                if FvAttribute == "FvUsedSizeEnable":
                    if self.FvAttributeDict[FvAttribute].upper() in ('TRUE', '1'):
                        self.UsedSizeEnable = True
                    continue
                self.FvInfFile.append("EFI_"            + \
                                          FvAttribute       + \
                                          ' = '             + \
                                          self.FvAttributeDict[FvAttribute] + \
                                          TAB_LINE_BREAK )
        if self.FvAlignment is not None:
            self.FvInfFile.append("EFI_FVB2_ALIGNMENT_"     + \
                                       self.FvAlignment.strip() + \
                                       " = TRUE"                + \
                                       TAB_LINE_BREAK)

        #
        # Generate FV extension header file
        #
        if not self.FvNameGuid:
            if len(self.FvExtEntryType) > 0 or self.UsedSizeEnable:
                GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))
        else:
            TotalSize = 16 + 4
            Buffer = bytearray()
            if self.UsedSizeEnable:
                TotalSize += (4 + 4)
                ## define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03
                #typedef  struct
                # {
                #    EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
                #    UINT32 UsedSize;
                # } EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE;
                Buffer += pack('HHL', 8, 3, 0)

            if self.FvNameString == 'TRUE':
                #
                # Create EXT entry for FV UI name
                # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C
                #
                FvUiLen = len(self.UiFvName)
                TotalSize += (FvUiLen + 16 + 4)
                Guid = FV_UI_EXT_ENTY_GUID.split('-')
                #
                # Layout:
                #   EFI_FIRMWARE_VOLUME_EXT_ENTRY: size 4
                #   GUID: size 16
                #   FV UI name
                #
                Buffer += (pack('HH', (FvUiLen + 16 + 4), 0x0002)
                           + PackGUID(Guid)
                           + self.UiFvName.encode('utf-8'))

            for Index in range (0, len(self.FvExtEntryType)):
                if self.FvExtEntryType[Index] == 'FILE':
                    # check if the path is absolute or relative
                    if os.path.isabs(self.FvExtEntryData[Index]):
                        FileFullPath = os.path.normpath(self.FvExtEntryData[Index])
                    else:
                        FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))
                    # check if the file path exists or not
                    if not os.path.isfile(FileFullPath):
                        GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))
                    FvExtFile = open (FileFullPath, 'rb')
                    FvExtFile.seek(0, 2)
                    Size = FvExtFile.tell()
                    if Size >= 0x10000:
                        GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
                    TotalSize += (Size + 4)
                    FvExtFile.seek(0)
                    Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
                    Buffer += FvExtFile.read()
                    FvExtFile.close()
                if self.FvExtEntryType[Index] == 'DATA':
                    ByteList = self.FvExtEntryData[Index].split(',')
                    Size = len (ByteList)
                    if Size >= 0x10000:
                        GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
                    TotalSize += (Size + 4)
                    Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
                    for Index1 in range (0, Size):
                        Buffer += pack('B', int(ByteList[Index1], 16))

            Guid = self.FvNameGuid.split('-')
            Buffer = PackGUID(Guid) + pack('=L', TotalSize) + Buffer

            #
            # Generate FV extension header file if the total size is not zero
            #
            if TotalSize > 0:
                FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')
                FvExtHeaderFile = BytesIO()
                FvExtHeaderFile.write(Buffer)
                Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True)
                FvExtHeaderFile.close()
                if Changed:
                  if os.path.exists (self.InfFileName):
                    os.remove (self.InfFileName)
                self.FvInfFile.append("EFI_FV_EXT_HEADER_FILE_NAME = "      + \
                                           FvExtHeaderFileName                  + \
                                           TAB_LINE_BREAK)

        #
        # Add [Files]
        #
        self.FvInfFile.append("[files]" + TAB_LINE_BREAK)
Example #2
0
    def GenFmpCapsule(self):
        #
        # Generate capsule header
        # typedef struct {
        #     EFI_GUID          CapsuleGuid;
        #     UINT32            HeaderSize;
        #     UINT32            Flags;
        #     UINT32            CapsuleImageSize;
        # } EFI_CAPSULE_HEADER;
        #
        Header = BytesIO()
        #
        # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
        #
        Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
        HdrSize = 0
        if 'CAPSULE_HEADER_SIZE' in self.TokensDict:
            Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))
            HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)
        else:
            Header.write(pack('=I', 0x20))
            HdrSize = 0x20
        Flags = 0
        if 'CAPSULE_FLAGS' in self.TokensDict:
            for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):
                flag = flag.strip()
                if flag == 'PopulateSystemTable':
                    Flags |= 0x00010000 | 0x00020000
                elif flag == 'PersistAcrossReset':
                    Flags |= 0x00010000
                elif flag == 'InitiateReset':
                    Flags |= 0x00040000
        Header.write(pack('=I', Flags))
        #
        # typedef struct {
        #     UINT32 Version;
        #     UINT16 EmbeddedDriverCount;
        #     UINT16 PayloadItemCount;
        #     // UINT64 ItemOffsetList[];
        # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
        #
        FwMgrHdr = BytesIO()
        if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:
            FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))
        else:
            FwMgrHdr.write(pack('=I', 0x00000001))
        FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))
        FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))

        #
        # typedef struct _WIN_CERTIFICATE {
        #   UINT32 dwLength;
        #   UINT16 wRevision;
        #   UINT16 wCertificateType;
        # //UINT8 bCertificate[ANYSIZE_ARRAY];
        # } WIN_CERTIFICATE;
        #
        # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
        #   WIN_CERTIFICATE Hdr;
        #   EFI_GUID        CertType;
        # //UINT8 CertData[ANYSIZE_ARRAY];
        # } WIN_CERTIFICATE_UEFI_GUID;
        #
        # typedef struct {
        #   UINT64                    MonotonicCount;
        #   WIN_CERTIFICATE_UEFI_GUID AuthInfo;
        # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
        #
        # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
        #   EFI_GUID HashType;
        #   UINT8 PublicKey[256];
        #   UINT8 Signature[256];
        # } EFI_CERT_BLOCK_RSA_2048_SHA256;
        #

        PreSize = FwMgrHdrSize
        Content = BytesIO()
        for driver in self.CapsuleDataList:
            FileName = driver.GenCapsuleSubItem()
            FwMgrHdr.write(pack('=Q', PreSize))
            PreSize += os.path.getsize(FileName)
            File = open(FileName, 'rb')
            Content.write(File.read())
            File.close()
        for fmp in self.FmpPayloadList:
            if fmp.Existed:
                FwMgrHdr.write(pack('=Q', PreSize))
                PreSize += len(fmp.Buffer)
                Content.write(fmp.Buffer)
                continue
            if fmp.ImageFile:
                for Obj in fmp.ImageFile:
                    fmp.ImageFile = Obj.GenCapsuleSubItem()
            if fmp.VendorCodeFile:
                for Obj in fmp.VendorCodeFile:
                    fmp.VendorCodeFile = Obj.GenCapsuleSubItem()
            if fmp.Certificate_Guid:
                ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)
                CmdOption = ''
                CapInputFile = fmp.ImageFile
                if not os.path.isabs(fmp.ImageFile):
                    CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)
                CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'
                if ExternalTool is None:
                    EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)
                else:
                    CmdOption += ExternalTool
                if ExternalOption:
                    CmdOption = CmdOption + ' ' + ExternalOption
                CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile
                CmdList = CmdOption.split()
                GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")
                if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:
                    dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)
                else:
                    dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256
                fmp.ImageFile = CapOutputTmp
                AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]
                fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)
            else:
                fmp.Buffer = fmp.GenCapsuleSubItem()
            FwMgrHdr.write(pack('=Q', PreSize))
            PreSize += len(fmp.Buffer)
            Content.write(fmp.Buffer)
        BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
        Header.write(pack('=I', HdrSize + BodySize))
        #
        # The real capsule header structure is 28 bytes
        #
        Header.write(b'\x00'*(HdrSize-28))
        Header.write(FwMgrHdr.getvalue())
        Header.write(Content.getvalue())
        #
        # Generate FMP capsule file
        #
        CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'
        SaveFileOnChange(CapOutputFile, Header.getvalue(), True)
        return CapOutputFile