1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright (c) 2016 Google, Inc 3# Written by Simon Glass <sjg@chromium.org> 4# 5# Entry-type module for Intel Management Engine binary blob 6# 7 8from collections import OrderedDict 9 10from binman.entry import Entry 11from binman.etype.blob_ext import Entry_blob_ext 12from dtoc import fdt_util 13from u_boot_pylib import tools 14 15class Entry_intel_ifwi(Entry_blob_ext): 16 """Intel Integrated Firmware Image (IFWI) file 17 18 Properties / Entry arguments: 19 - filename: Filename of file to read into entry. This is either the 20 IFWI file itself, or a file that can be converted into one using a 21 tool 22 - convert-fit: If present this indicates that the ifwitool should be 23 used to convert the provided file into a IFWI. 24 25 This file contains code and data used by the SoC that is required to make 26 it work. It includes U-Boot TPL, microcode, things related to the CSE 27 (Converged Security Engine, the microcontroller that loads all the firmware) 28 and other items beyond the wit of man. 29 30 A typical filename is 'ifwi.bin' for an IFWI file, or 'fitimage.bin' for a 31 file that will be converted to an IFWI. 32 33 The position of this entry is generally set by the intel-descriptor entry. 34 35 The contents of the IFWI are specified by the subnodes of the IFWI node. 36 Each subnode describes an entry which is placed into the IFWFI with a given 37 sub-partition (and optional entry name). 38 39 Properties for subnodes: 40 - ifwi-subpart: sub-parition to put this entry into, e.g. "IBBP" 41 - ifwi-entry: entry name t use, e.g. "IBBL" 42 - ifwi-replace: if present, indicates that the item should be replaced 43 in the IFWI. Otherwise it is added. 44 45 See README.x86 for information about x86 binary blobs. 46 """ 47 def __init__(self, section, etype, node): 48 super().__init__(section, etype, node) 49 self._convert_fit = fdt_util.GetBool(self._node, 'convert-fit') 50 self._ifwi_entries = OrderedDict() 51 52 def ReadNode(self): 53 self.ReadEntries() 54 super().ReadNode() 55 56 def _BuildIfwi(self): 57 """Build the contents of the IFWI and write it to the 'data' property""" 58 # Create the IFWI file if needed 59 if self._convert_fit: 60 inname = self._pathname 61 outname = tools.get_output_filename('ifwi.bin') 62 if self.ifwitool.create_ifwi(inname, outname) is None: 63 # Bintool is missing; just create a zeroed ifwi.bin 64 self.record_missing_bintool(self.ifwitool) 65 self.SetContents(tools.get_bytes(0, 1024)) 66 67 self._filename = 'ifwi.bin' 68 self._pathname = outname 69 else: 70 # Provide a different code path here to ensure we have test coverage 71 outname = self._pathname 72 73 # Delete OBBP if it is there, then add the required new items 74 if self.ifwitool.delete_subpart(outname, 'OBBP') is None: 75 # Bintool is missing; just use zero data 76 self.record_missing_bintool(self.ifwitool) 77 self.SetContents(tools.get_bytes(0, 1024)) 78 return True 79 80 for entry in self._ifwi_entries.values(): 81 # First get the input data and put it in a file 82 data = entry.GetPaddedData() 83 uniq = self.GetUniqueName() 84 input_fname = tools.get_output_filename('input.%s' % uniq) 85 tools.write_file(input_fname, data) 86 87 # At this point we know that ifwitool is present, so we don't need 88 # to check for None here 89 self.ifwitool.add_subpart( 90 outname, entry._ifwi_subpart, entry._ifwi_entry_name, 91 input_fname, entry._ifwi_replace) 92 93 self.ReadBlobContents() 94 return True 95 96 def ObtainContents(self): 97 """Get the contents for the IFWI 98 99 Unfortunately we cannot create anything from scratch here, as Intel has 100 tools which create precursor binaries with lots of data and settings, 101 and these are not incorporated into binman. 102 103 The first step is to get a file in the IFWI format. This is either 104 supplied directly or is extracted from a fitimage using the 'create' 105 subcommand. 106 107 After that we delete the OBBP sub-partition and add each of the files 108 that we want in the IFWI file, one for each sub-entry of the IWFI node. 109 """ 110 self._pathname = tools.get_input_filename(self._filename, 111 self.section.GetAllowMissing()) 112 # Allow the file to be missing 113 if not self._pathname: 114 self.SetContents(b'') 115 self.missing = True 116 return True 117 for entry in self._ifwi_entries.values(): 118 if not entry.ObtainContents(): 119 return False 120 return self._BuildIfwi() 121 122 def ProcessContents(self): 123 if self.missing: 124 return True 125 orig_data = self.data 126 self._BuildIfwi() 127 same = orig_data == self.data 128 return same 129 130 def ReadEntries(self): 131 """Read the subnodes to find out what should go in this IFWI""" 132 for node in self._node.subnodes: 133 entry = Entry.Create(self.section, node) 134 entry.ReadNode() 135 entry._ifwi_replace = fdt_util.GetBool(node, 'ifwi-replace') 136 entry._ifwi_subpart = fdt_util.GetString(node, 'ifwi-subpart') 137 entry._ifwi_entry_name = fdt_util.GetString(node, 'ifwi-entry') 138 self._ifwi_entries[entry._ifwi_subpart] = entry 139 140 def WriteSymbols(self, section): 141 """Write symbol values into binary files for access at run time""" 142 if not self.missing: 143 for entry in self._ifwi_entries.values(): 144 entry.WriteSymbols(self) 145 146 def AddBintools(self, btools): 147 super().AddBintools(btools) 148 self.ifwitool = self.AddBintool(btools, 'ifwitool') 149