<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="ProgId" content="Word.Document">
<meta name="Generator" content="Microsoft Word 15">
<meta name="Originator" content="Microsoft Word 15">
<link rel="File-List" href="cid:filelist.xml@01D6B80B.823CC4E0"><link rel="Edit-Time-Data" href="cid:editdata.mso"><!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>130</w:Zoom>
<w:DocumentKind>DocumentEmail</w:DocumentKind>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:EnvelopeVis/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:DoNotExpandShiftReturn/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="false" DefSemiHidden="false" DefQFormat="false" DefPriority="99" LatentStyleCount="376">
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index 9"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" Name="toc 9"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Normal Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="footnote text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="annotation text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="header"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="footer"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="index heading"/>
<w:LsdException Locked="false" Priority="35" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="table of figures"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="envelope address"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="envelope return"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="footnote reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="annotation reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="line number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="page number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="endnote reference"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="endnote text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="table of authorities"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="macro"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="toa heading"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Bullet"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Number"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Bullet 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Bullet 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Bullet 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Bullet 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Number 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Number 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Number 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Number 5"/>
<w:LsdException Locked="false" Priority="10" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Closing"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Signature"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="true" UnhideWhenUsed="true" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Continue"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Continue 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Continue 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Continue 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="List Continue 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Message Header"/>
<w:LsdException Locked="false" Priority="11" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Salutation"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Date"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text First Indent"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text First Indent 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Note Heading"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text Indent 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Body Text Indent 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Block Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Hyperlink"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="FollowedHyperlink"/>
<w:LsdException Locked="false" Priority="22" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Document Map"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Plain Text"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="E-mail Signature"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Top of Form"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Bottom of Form"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Normal (Web)"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Acronym"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Address"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Cite"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Code"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Definition"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Keyboard"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Preformatted"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Sample"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Typewriter"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="HTML Variable"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="annotation subject"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="No List"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Outline List 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Outline List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Outline List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Simple 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Simple 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Simple 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Classic 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Classic 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Classic 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Classic 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Colorful 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Colorful 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Colorful 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Columns 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Columns 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Columns 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Columns 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Columns 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Grid 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 4"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 5"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 7"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table List 8"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table 3D effects 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table 3D effects 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table 3D effects 3"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Contemporary"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Elegant"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Professional"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Subtle 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Subtle 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Web 1"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Table Web 2"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Balloon Text"/>
<w:LsdException Locked="false" Priority="39" Name="Table Grid"/>
<w:LsdException Locked="false" SemiHidden="true" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" SemiHidden="true" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" SemiHidden="true" UnhideWhenUsed="true" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" SemiHidden="true" UnhideWhenUsed="true" QFormat="true" Name="TOC Heading"/>
<w:LsdException Locked="false" Priority="41" Name="Plain Table 1"/>
<w:LsdException Locked="false" Priority="42" Name="Plain Table 2"/>
<w:LsdException Locked="false" Priority="43" Name="Plain Table 3"/>
<w:LsdException Locked="false" Priority="44" Name="Plain Table 4"/>
<w:LsdException Locked="false" Priority="45" Name="Plain Table 5"/>
<w:LsdException Locked="false" Priority="40" Name="Grid Table Light"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 1"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 1"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 1"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 1"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 1"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 2"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 2"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 2"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 2"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 2"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 3"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 3"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 3"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 3"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 3"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 4"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 4"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 4"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 4"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 4"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 5"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 5"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 5"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 5"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 5"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light Accent 6"/>
<w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 6"/>
<w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 6"/>
<w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 6"/>
<w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 6"/>
<w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 1"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 1"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 1"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 1"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 1"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 1"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 2"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 2"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 2"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 2"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 2"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 2"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 3"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 3"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 3"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 3"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 3"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 3"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 4"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 4"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 4"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 4"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 4"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 4"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 5"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 5"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 5"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 5"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 5"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 5"/>
<w:LsdException Locked="false" Priority="46" Name="List Table 1 Light Accent 6"/>
<w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 6"/>
<w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 6"/>
<w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 6"/>
<w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 6"/>
<w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful Accent 6"/>
<w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful Accent 6"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Mention"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Smart Hyperlink"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Hashtag"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Unresolved Mention"/>
<w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" Name="Smart Link"/>
</w:LatentStyles>
</xml><![endif]--><style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-alt:"Calisto MT";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:-536869121 1107305727 33554432 0 415 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-alt:Calibri;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-469750017 -1073732485 9 0 511 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin:0in;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-fareast-font-family:Calibri;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:#954F72;
text-decoration:underline;
text-underline:single;}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-style-unhide:no;
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-fareast-font-family:Calibri;}
span.EmailStyle20
{mso-style-type:personal-reply;
mso-style-noshow:yes;
mso-style-unhide:no;
mso-ansi-font-size:11.0pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-size:10.0pt;
mso-ansi-font-size:10.0pt;
mso-bidi-font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 10]><style>/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman",serif;}
</style><![endif]--><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="#954F72" style="tab-interval:.5in">
<div class="WordSection1">
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman"">Hi Kilian,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman"">2983 was resolved by a previous commit.<span style="mso-spacerun:yes">
</span>Thank you for the reminder to update the BZ with the details.<span style="mso-spacerun:yes">
</span>It is closed now.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman"">Mike<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:"Times New Roman""><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="mso-fareast-font-family:"Times New Roman"">From:</span></b><span style="mso-fareast-font-family:"Times New Roman""> devel@edk2.groups.io <devel@edk2.groups.io>
<b>On Behalf Of </b>Kilian Kegel<br>
<b>Sent:</b> Tuesday, November 10, 2020 8:17 PM<br>
<b>To:</b> devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>; Michael Kubacki <michael.kubacki@outlook.com><br>
<b>Cc:</b> Qian, Yi <yi.qian@intel.com>; Sun, Zailiang <zailiang.sun@intel.com><br>
<b>Subject:</b> Re: [edk2-devel] [edk2-platforms][PATCH v1 1/1] Vlv2TbltDevicePkg/FmpDeviceLib: Add LastAttemptStatus compatibility<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span lang="DE" style="mso-ansi-language:DE">Hi all,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="DE" style="mso-ansi-language:DE"><o:p> </o:p></span></p>
<p class="MsoNormal">if this patch also affects <a href="https://bugzilla.tianocore.org/show_bug.cgi?id=2983">
https://bugzilla.tianocore.org/show_bug.cgi?id=2983</a>, please close it.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal">Kilian<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="mso-outline-level:1"><b>Von: </b><a href="mailto:michael.d.kinney@intel.com">Michael D Kinney</a><br>
<b>Gesendet: </b>Wednesday, November 11, 2020 4:03 AM<br>
<b>An: </b><a href="mailto:michael.kubacki@outlook.com">Michael Kubacki</a>; <a href="mailto:devel@edk2.groups.io">
devel@edk2.groups.io</a>; <a href="mailto:michael.d.kinney@intel.com">Kinney, Michael D</a><br>
<b>Cc: </b><a href="mailto:yi.qian@intel.com">Qian, Yi</a>; <a href="mailto:zailiang.sun@intel.com">
Sun, Zailiang</a><br>
<b>Betreff: </b>Re: [edk2-devel] [edk2-platforms][PATCH v1 1/1] Vlv2TbltDevicePkg/FmpDeviceLib: Add LastAttemptStatus compatibility<o:p></o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">Hi Michael,<br>
<br>
This patch has been merged.<br>
<br>
Thanks,<br>
<br>
Mike<br>
<br>
> -----Original Message-----<br>
> From: Michael Kubacki <<a href="mailto:michael.kubacki@outlook.com">michael.kubacki@outlook.com</a>><br>
> Sent: Thursday, November 5, 2020 12:36 PM<br>
> To: Kinney, Michael D <<a href="mailto:michael.d.kinney@intel.com">michael.d.kinney@intel.com</a>>;
<a href="mailto:devel@edk2.groups.io">devel@edk2.groups.io</a><br>
> Cc: Qian, Yi <<a href="mailto:yi.qian@intel.com">yi.qian@intel.com</a>>; Sun, Zailiang <<a href="mailto:zailiang.sun@intel.com">zailiang.sun@intel.com</a>><br>
> Subject: Re: [edk2-platforms][PATCH v1 1/1] Vlv2TbltDevicePkg/FmpDeviceLib: Add LastAttemptStatus compatibility<br>
> <br>
> Hi Mike,<br>
> <br>
> I saw other Vlv2TbltDevicePkg patches were merged yesterday. Do you know<br>
> when this patch will be merged?<br>
> <br>
> Thanks,<br>
> Michael<br>
> <br>
> On 10/28/2020 6:12 PM, Kinney, Michael D wrote:<br>
> > Reviewed-by: Michael D Kinney <<a href="mailto:michael.d.kinney@intel.com">michael.d.kinney@intel.com</a>><br>
> ><br>
> > I also verified build and boot and FMP based capsule updates work as expected.<br>
> ><br>
> > Tested-by: Michael D Kinney <<a href="mailto:Michael.d.kinney@intel.com">Michael.d.kinney@intel.com</a>><br>
> ><br>
> > Thanks,<br>
> ><br>
> > Mike<br>
> ><br>
> ><br>
> >> -----Original Message-----<br>
> >> From: <a href="mailto:michael.kubacki@outlook.com">michael.kubacki@outlook.com</a> <<a href="mailto:michael.kubacki@outlook.com">michael.kubacki@outlook.com</a>><br>
> >> Sent: Thursday, October 1, 2020 2:59 PM<br>
> >> To: <a href="mailto:devel@edk2.groups.io">devel@edk2.groups.io</a><br>
> >> Cc: Kinney, Michael D <<a href="mailto:michael.d.kinney@intel.com">michael.d.kinney@intel.com</a>>; Qian, Yi <<a href="mailto:yi.qian@intel.com">yi.qian@intel.com</a>>; Sun, Zailiang<br>
> <<a href="mailto:zailiang.sun@intel.com">zailiang.sun@intel.com</a>><br>
> >> Subject: [edk2-platforms][PATCH v1 1/1] Vlv2TbltDevicePkg/FmpDeviceLib: Add LastAttemptStatus compatibility<br>
> >><br>
> >> From: Michael Kubacki <<a href="mailto:michael.kubacki@microsoft.com">michael.kubacki@microsoft.com</a>><br>
> >><br>
> >> Makes the changes necessary for these library instances of<br>
> >> FmpDeviceLib to be compatible with new functions added recently<br>
> >> to FmpDeviceLib.<br>
> >><br>
> >> Two new functions were introduced in FmpDeviceLib to allow a<br>
> >> library instance to return a Last Attempt Status code during<br>
> >> check image and set image operations:<br>
> >> 1. FmpDeviceCheckImageWithStatus ( )<br>
> >> 2. FmpDeviceSetImageWithStatus ( )<br>
> >><br>
> >> FmpDxe (in FmpDevicePkg) will begin calling these new functions<br>
> >> instead of the previous functions. Therefore, this change:<br>
> >> 1. Adds these functions to Vlv2TbltDevicePkg implementations<br>
> >> 2. Moves the main functionality to these new functions<br>
> >> 3. Updates the old functions to call the new functions<br>
> >> (for backward compatibility)<br>
> >><br>
> >> Note: As of this commit, the Vlv2TbltDevicePkg build is broken<br>
> >> due to:<br>
> >> 1. A required RngLib library instance not defined by the platform<br>
> >> 2. Other FMP libraries not being defined by the platform<br>
> >> (e.g. FmpDependencyLib, FmpDependencyCheckLib, etc.)<br>
> >><br>
> >> Those changes were fixed locally to test the changes in this commit<br>
> >> but maintainers should make the proper changes for those issues.<br>
> >><br>
> >> Cc: Michael D Kinney <<a href="mailto:michael.d.kinney@intel.com">michael.d.kinney@intel.com</a>><br>
> >> Cc: Yi Qian <<a href="mailto:yi.qian@intel.com">yi.qian@intel.com</a>><br>
> >> Cc: Zailiang Sun <<a href="mailto:zailiang.sun@intel.com">zailiang.sun@intel.com</a>><br>
> >> Signed-off-by: Michael Kubacki <<a href="mailto:michael.kubacki@microsoft.com">michael.kubacki@microsoft.com</a>><br>
> >> ---<br>
> >><br>
> >> Notes:<br>
> >> Only build was checked, I do not have access to a<br>
> >> VLV2 device for testing.<br>
> >><br>
> >> Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c | 299 +++++++++++++++-----<br>
> >> Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLibSample/FmpDeviceLib.c | 284 ++++++++++++++-----<br>
> >> 2 files changed, 446 insertions(+), 137 deletions(-)<br>
> >><br>
> >> diff --git a/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c<br>
> >> b/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c<br>
> >> index d8c9036012ad..df8a36d9854c 100644<br>
> >> --- a/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c<br>
> >> +++ b/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c<br>
> >> @@ -1,6 +1,6 @@<br>
> >> /**<br>
> >><br>
> >> -Copyright (c) 2016, Microsoft Corporation. All rights reserved.<br>
> >> +Copyright (c) Microsoft Corporation.<BR><br>
> >> Copyright (c) 2019, Intel Corporation. All rights reserved.<br>
> >><br>
> >> SPDX-License-Identifier: BSD-2-Clause-Patent<br>
> >> @@ -8,7 +8,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent<br>
> >> **/<br>
> >><br>
> >> #include <PiDxe.h><br>
> >> -<br>
> >> +#include <LastAttemptStatus.h><br>
> >> +#include <Guid/SystemResourceTable.h><br>
> >> #include <Library/FmpDeviceLib.h><br>
> >><br>
> >> #include <Library/DebugLib.h><br>
> >> @@ -444,20 +445,17 @@ FmpDeviceGetImage (<br>
> >> }<br>
> >><br>
> >> /**<br>
> >> - Updates the firmware image of the device.<br>
> >> -<br>
> >> - This function updates the hardware with the new firmware image. This function<br>
> >> - returns EFI_UNSUPPORTED if the firmware image is not updatable. If the<br>
> >> - firmware image is updatable, the function should perform the following minimal<br>
> >> - validations before proceeding to do the firmware image update.<br>
> >> - - Validate the image is a supported image for this device. The function<br>
> >> - returns EFI_ABORTED if the image is unsupported. The function can<br>
> >> - optionally provide more detailed information on why the image is not a<br>
> >> - supported image.<br>
> >> - - Validate the data from VendorCode if not null. Image validation must be<br>
> >> - performed before VendorCode data validation. VendorCode data is ignored<br>
> >> - or considered invalid if image validation failed. The function returns<br>
> >> - EFI_ABORTED if the data is invalid.<br>
> >> + Updates a firmware device with a new firmware image. This function returns<br>
> >> + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image<br>
> >> + is updatable, the function should perform the following minimal validations<br>
> >> + before proceeding to do the firmware image update.<br>
> >> + - Validate that the image is a supported image for this firmware device.<br>
> >> + Return EFI_ABORTED if the image is not supported. Additional details<br>
> >> + on why the image is not a supported image may be returned in AbortReason.<br>
> >> + - Validate the data from VendorCode if is not NULL. Firmware image<br>
> >> + validation must be performed before VendorCode data validation.<br>
> >> + VendorCode data is ignored or considered invalid if image validation<br>
> >> + fails. Return EFI_ABORTED if the VendorCode data is invalid.<br>
> >><br>
> >> VendorCode enables vendor to implement vendor-specific firmware image update<br>
> >> policy. Null if the caller did not specify the policy or use the default<br>
> >> @@ -470,38 +468,56 @@ FmpDeviceGetImage (<br>
> >> have the option to provide a more detailed description of the abort reason to<br>
> >> the caller.<br>
> >><br>
> >> - @param[in] Image Points to the new image.<br>
> >> - @param[in] ImageSize Size of the new image in bytes.<br>
> >> + @param[in] Image Points to the new firmware image.<br>
> >> + @param[in] ImageSize Size, in bytes, of the new firmware image.<br>
> >> @param[in] VendorCode This enables vendor to implement vendor-specific<br>
> >> - firmware image update policy. Null indicates the<br>
> >> - caller did not specify the policy or use the<br>
> >> + firmware image update policy. NULL indicates<br>
> >> + the caller did not specify the policy or use the<br>
> >> default policy.<br>
> >> - @param[in] Progress A function used by the driver to report the<br>
> >> - progress of the firmware update.<br>
> >> - @param[in] CapsuleFwVersion FMP Payload Header version of the image.<br>
> >> - @param[out] AbortReason A pointer to a pointer to a null-terminated<br>
> >> - string providing more details for the aborted<br>
> >> - operation. The buffer is allocated by this<br>
> >> - function with AllocatePool(), and it is the<br>
> >> - caller's responsibility to free it with a call<br>
> >> - to FreePool().<br>
> >> + @param[in] Progress A function used to report the progress of<br>
> >> + updating the firmware device with the new<br>
> >> + firmware image.<br>
> >> + @param[in] CapsuleFwVersion The version of the new firmware image from the<br>
> >> + update capsule that provided the new firmware<br>
> >> + image.<br>
> >> + @param[out] AbortReason A pointer to a pointer to a Null-terminated<br>
> >> + Unicode string providing more details on an<br>
> >> + aborted operation. The buffer is allocated by<br>
> >> + this function with<br>
> >> + EFI_BOOT_SERVICES.AllocatePool(). It is the<br>
> >> + caller's responsibility to free this buffer with<br>
> >> + EFI_BOOT_SERVICES.FreePool().<br>
> >> + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt<br>
> >> + status to report back to the ESRT table in case<br>
> >> + of error. This value will only be checked when this<br>
> >> + function returns an error.<br>
> >><br>
> >> - @retval EFI_SUCCESS The device was successfully updated with the<br>
> >> - new image.<br>
> >> - @retval EFI_ABORTED The operation is aborted.<br>
> >> + The return status code must fall in the range of<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.<br>
> >> +<br>
> >> + If the value falls outside this range, it will be converted<br>
> >> + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.<br>
> >> +<br>
> >> + @retval EFI_SUCCESS The firmware device was successfully updated<br>
> >> + with the new firmware image.<br>
> >> + @retval EFI_ABORTED The operation is aborted. Additional details<br>
> >> + are provided in AbortReason.<br>
> >> @retval EFI_INVALID_PARAMETER The Image was NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER LastAttemptStatus was NULL.<br>
> >> @retval EFI_UNSUPPORTED The operation is not supported.<br>
> >><br>
> >> **/<br>
> >> EFI_STATUS<br>
> >> EFIAPI<br>
> >> -FmpDeviceSetImage (<br>
> >> +FmpDeviceSetImageWithStatus (<br>
> >> IN CONST VOID *Image,<br>
> >> IN UINTN ImageSize,<br>
> >> - IN CONST VOID *VendorCode,<br>
> >> - IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,<br>
> >> + IN CONST VOID *VendorCode, OPTIONAL<br>
> >> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL<br>
> >> IN UINT32 CapsuleFwVersion,<br>
> >> - OUT CHAR16 **AbortReason<br>
> >> + OUT CHAR16 **AbortReason,<br>
> >> + OUT UINT32 *LastAttemptStatus<br>
> >> )<br>
> >> {<br>
> >> EFI_STATUS Status;<br>
> >> @@ -513,25 +529,27 @@ FmpDeviceSetImage (<br>
> >> UINTN BytesWritten;<br>
> >><br>
> >> Updateable = 0;<br>
> >> - Status = FmpDeviceCheckImage (Image, ImageSize, &Updateable);<br>
> >> + Status = FmpDeviceCheckImageWithStatus (Image, ImageSize, &Updateable, LastAttemptStatus);<br>
> >> if (EFI_ERROR (Status)) {<br>
> >> - DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Check Image failed with %r.\n", Status));<br>
> >> + DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Check Image failed with %r.\n", Status));<br>
> >> return Status;<br>
> >> }<br>
> >><br>
> >> if (Updateable != IMAGE_UPDATABLE_VALID) {<br>
> >> - DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Check Image returned that the Image was not valid for update. Updatable<br>
> >> value = 0x%X.\n", Updateable));<br>
> >> + DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Check Image returned that the Image was not valid for update.<br>
> >> Updatable value = 0x%X.\n", Updateable));<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> return EFI_ABORTED;<br>
> >> }<br>
> >><br>
> >> if (Progress == NULL) {<br>
> >> - DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Invalid progress callback\n"));<br>
> >> + DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Invalid progress callback\n"));<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> return EFI_INVALID_PARAMETER;<br>
> >> }<br>
> >><br>
> >> Status = Progress (15);<br>
> >> if (EFI_ERROR (Status)) {<br>
> >> - DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Progress Callback failed with Status %r.\n", Status));<br>
> >> + DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));<br>
> >> }<br>
> >><br>
> >> //<br>
> >> @@ -539,7 +557,7 @@ FmpDeviceSetImage (<br>
> >> //<br>
> >> Progress (20);<br>
> >> if (EFI_ERROR (Status)) {<br>
> >> - DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Progress Callback failed with Status %r.\n", Status));<br>
> >> + DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));<br>
> >> }<br>
> >><br>
> >> //<br>
> >> @@ -553,11 +571,11 @@ FmpDeviceSetImage (<br>
> >><br>
> >> // Progress (Percentage);<br>
> >> // if (EFI_ERROR (Status)) {<br>
> >> -// DEBUG((DEBUG_ERROR, "FmpDeviceSetImage - Progress Callback failed with Status %r.\n", Status));<br>
> >> +// DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));<br>
> >> // }<br>
> >> }<br>
> >><br>
> >> - DEBUG ((DEBUG_INFO, "FmpDeviceSetImage - %d Images ...\n", ARRAY_SIZE (mUpdateConfigData)));<br>
> >> + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %d Images ...\n", ARRAY_SIZE (mUpdateConfigData)));<br>
> >><br>
> >> if (ARRAY_SIZE (mUpdateConfigData) == 0) {<br>
> >> DEBUG((DEBUG_INFO, "PlatformUpdate: BaseAddress - 0x%lx ImageOffset - 0x%x Length - 0x%x\n", 0, 0, ImageSize));<br>
> >> @@ -605,11 +623,173 @@ FmpDeviceSetImage (<br>
> >> BytesWritten += ConfigData->Length;<br>
> >> }<br>
> >><br>
> >> - DEBUG ((DEBUG_INFO, "FmpDeviceSetImage - %r\n", Status));<br>
> >> + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %r\n", Status));<br>
> >> +<br>
> >> + if (EFI_ERROR (Status)) {<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + }<br>
> >><br>
> >> return Status;<br>
> >> }<br>
> >><br>
> >> +/**<br>
> >> + Updates the firmware image of the device.<br>
> >> +<br>
> >> + This function updates the hardware with the new firmware image. This function<br>
> >> + returns EFI_UNSUPPORTED if the firmware image is not updatable. If the<br>
> >> + firmware image is updatable, the function should perform the following minimal<br>
> >> + validations before proceeding to do the firmware image update.<br>
> >> + - Validate the image is a supported image for this device. The function<br>
> >> + returns EFI_ABORTED if the image is unsupported. The function can<br>
> >> + optionally provide more detailed information on why the image is not a<br>
> >> + supported image.<br>
> >> + - Validate the data from VendorCode if not null. Image validation must be<br>
> >> + performed before VendorCode data validation. VendorCode data is ignored<br>
> >> + or considered invalid if image validation failed. The function returns<br>
> >> + EFI_ABORTED if the data is invalid.<br>
> >> +<br>
> >> + VendorCode enables vendor to implement vendor-specific firmware image update<br>
> >> + policy. Null if the caller did not specify the policy or use the default<br>
> >> + policy. As an example, vendor can implement a policy to allow an option to<br>
> >> + force a firmware image update when the abort reason is due to the new firmware<br>
> >> + image version is older than the current firmware image version or bad image<br>
> >> + checksum. Sensitive operations such as those wiping the entire firmware image<br>
> >> + and render the device to be non-functional should be encoded in the image<br>
> >> + itself rather than passed with the VendorCode. AbortReason enables vendor to<br>
> >> + have the option to provide a more detailed description of the abort reason to<br>
> >> + the caller.<br>
> >> +<br>
> >> + @param[in] Image Points to the new image.<br>
> >> + @param[in] ImageSize Size of the new image in bytes.<br>
> >> + @param[in] VendorCode This enables vendor to implement vendor-specific<br>
> >> + firmware image update policy. Null indicates the<br>
> >> + caller did not specify the policy or use the<br>
> >> + default policy.<br>
> >> + @param[in] Progress A function used by the driver to report the<br>
> >> + progress of the firmware update.<br>
> >> + @param[in] CapsuleFwVersion FMP Payload Header version of the image.<br>
> >> + @param[out] AbortReason A pointer to a pointer to a null-terminated<br>
> >> + string providing more details for the aborted<br>
> >> + operation. The buffer is allocated by this<br>
> >> + function with AllocatePool(), and it is the<br>
> >> + caller's responsibility to free it with a call<br>
> >> + to FreePool().<br>
> >> +<br>
> >> + @retval EFI_SUCCESS The device was successfully updated with the<br>
> >> + new image.<br>
> >> + @retval EFI_ABORTED The operation is aborted.<br>
> >> + @retval EFI_INVALID_PARAMETER The Image was NULL.<br>
> >> + @retval EFI_UNSUPPORTED The operation is not supported.<br>
> >> +<br>
> >> +**/<br>
> >> +EFI_STATUS<br>
> >> +EFIAPI<br>
> >> +FmpDeviceSetImage (<br>
> >> + IN CONST VOID *Image,<br>
> >> + IN UINTN ImageSize,<br>
> >> + IN CONST VOID *VendorCode,<br>
> >> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,<br>
> >> + IN UINT32 CapsuleFwVersion,<br>
> >> + OUT CHAR16 **AbortReason<br>
> >> + )<br>
> >> +{<br>
> >> + UINT32 LastAttemptStatus;<br>
> >> +<br>
> >> + return FmpDeviceSetImageWithStatus (<br>
> >> + Image,<br>
> >> + ImageSize,<br>
> >> + VendorCode,<br>
> >> + Progress,<br>
> >> + CapsuleFwVersion,<br>
> >> + AbortReason,<br>
> >> + &LastAttemptStatus<br>
> >> + );<br>
> >> +}<br>
> >> +<br>
> >> +/**<br>
> >> + Checks if a new firmware image is valid for the firmware device. This<br>
> >> + function allows firmware update operation to validate the firmware image<br>
> >> + before FmpDeviceSetImage() is called.<br>
> >> +<br>
> >> + @param[in] Image Points to a new firmware image.<br>
> >> + @param[in] ImageSize Size, in bytes, of a new firmware image.<br>
> >> + @param[out] ImageUpdatable Indicates if a new firmware image is valid for<br>
> >> + a firmware update to the firmware device. The<br>
> >> + following values from the Firmware Management<br>
> >> + Protocol are supported:<br>
> >> + IMAGE_UPDATABLE_VALID<br>
> >> + IMAGE_UPDATABLE_INVALID<br>
> >> + IMAGE_UPDATABLE_INVALID_TYPE<br>
> >> + IMAGE_UPDATABLE_INVALID_OLD<br>
> >> + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE<br>
> >> + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt<br>
> >> + status to report back to the ESRT table in case<br>
> >> + of error. This value will only be checked when this<br>
> >> + function returns an error.<br>
> >> +<br>
> >> + The return status code must fall in the range of<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.<br>
> >> +<br>
> >> + If the value falls outside this range, it will be converted<br>
> >> + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.<br>
> >> +<br>
> >> + @retval EFI_SUCCESS The image was successfully checked. Additional<br>
> >> + status information is returned in<br>
> >> + ImageUpdatable.<br>
> >> + @retval EFI_INVALID_PARAMETER Image is NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER LastAttemptStatus is NULL.<br>
> >> +<br>
> >> +**/<br>
> >> +EFI_STATUS<br>
> >> +EFIAPI<br>
> >> +FmpDeviceCheckImageWithStatus (<br>
> >> + IN CONST VOID *Image,<br>
> >> + IN UINTN ImageSize,<br>
> >> + OUT UINT32 *ImageUpdatable,<br>
> >> + OUT UINT32 *LastAttemptStatus<br>
> >> + )<br>
> >> +{<br>
> >> + if (LastAttemptStatus == NULL) {<br>
> >> + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer Parameter is NULL.\n"));<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;<br>
> >> +<br>
> >> + if (ImageUpdatable == NULL) {<br>
> >> + DEBUG((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Parameter is NULL.\n"));<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> +<br>
> >> + //<br>
> >> + //Set to valid and then if any tests fail it will update this flag.<br>
> >> + //<br>
> >> + *ImageUpdatable = IMAGE_UPDATABLE_VALID;<br>
> >> +<br>
> >> + if (Image == NULL) {<br>
> >> + DEBUG((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter is NULL.\n"));<br>
> >> + //<br>
> >> + // Not sure if this is needed<br>
> >> + //<br>
> >> + *ImageUpdatable = IMAGE_UPDATABLE_INVALID;<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> +<br>
> >> + //<br>
> >> + // Make sure the image size is correct<br>
> >> + //<br>
> >> + if (ImageSize != PcdGet32 (PcdBiosRomSize)) {<br>
> >> + *ImageUpdatable = IMAGE_UPDATABLE_INVALID;<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> +<br>
> >> + return EFI_SUCCESS;<br>
> >> +}<br>
> >> +<br>
> >> /**<br>
> >> Checks if the firmware image is valid for the device.<br>
> >><br>
> >> @@ -633,34 +813,9 @@ FmpDeviceCheckImage (<br>
> >> OUT UINT32 *ImageUpdateable<br>
> >> )<br>
> >> {<br>
> >> - if (ImageUpdateable == NULL) {<br>
> >> - DEBUG((DEBUG_ERROR, "CheckImage - ImageUpdateable Pointer Parameter is NULL.\n"));<br>
> >> - return EFI_INVALID_PARAMETER;<br>
> >> - }<br>
> >> + UINT32 LastAttemptStatus;<br>
> >><br>
> >> - //<br>
> >> - //Set to valid and then if any tests fail it will update this flag.<br>
> >> - //<br>
> >> - *ImageUpdateable = IMAGE_UPDATABLE_VALID;<br>
> >> -<br>
> >> - if (Image == NULL) {<br>
> >> - DEBUG((DEBUG_ERROR, "CheckImage - Image Pointer Parameter is NULL.\n"));<br>
> >> - //<br>
> >> - // Not sure if this is needed<br>
> >> - //<br>
> >> - *ImageUpdateable = IMAGE_UPDATABLE_INVALID;<br>
> >> - return EFI_INVALID_PARAMETER;<br>
> >> - }<br>
> >> -<br>
> >> - //<br>
> >> - // Make sure the image size is correct<br>
> >> - //<br>
> >> - if (ImageSize != PcdGet32 (PcdBiosRomSize)) {<br>
> >> - *ImageUpdateable = IMAGE_UPDATABLE_INVALID;<br>
> >> - return EFI_INVALID_PARAMETER;<br>
> >> - }<br>
> >> -<br>
> >> - return EFI_SUCCESS;<br>
> >> + return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdateable, &LastAttemptStatus);<br>
> >> }<br>
> >><br>
> >> /**<br>
> >> diff --git a/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLibSample/FmpDeviceLib.c<br>
> >> b/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLibSample/FmpDeviceLib.c<br>
> >> index db0f238ea534..132b60844ad4 100644<br>
> >> --- a/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLibSample/FmpDeviceLib.c<br>
> >> +++ b/Platform/Intel/Vlv2TbltDevicePkg/Feature/Capsule/Library/FmpDeviceLibSample/FmpDeviceLib.c<br>
> >> @@ -1,6 +1,6 @@<br>
> >> /**<br>
> >><br>
> >> -Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR><br>
> >> +Copyright (c) Microsoft Corporation.<BR><br>
> >> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR><br>
> >><br>
> >> SPDX-License-Identifier: BSD-2-Clause-Patent<br>
> >> @@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent<br>
> >><br>
> >><br>
> >> #include <PiDxe.h><br>
> >> +#include <LastAttemptStatus.h><br>
> >> +#include <Guid/SystemResourceTable.h><br>
> >> #include <Library/DebugLib.h><br>
> >> #include <Protocol/FirmwareManagement.h><br>
> >> #include <Library/BaseLib.h><br>
> >> @@ -345,6 +347,131 @@ Return Value:<br>
> >> }//GetImage()<br>
> >><br>
> >><br>
> >> +/**<br>
> >> + Updates a firmware device with a new firmware image. This function returns<br>
> >> + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image<br>
> >> + is updatable, the function should perform the following minimal validations<br>
> >> + before proceeding to do the firmware image update.<br>
> >> + - Validate that the image is a supported image for this firmware device.<br>
> >> + Return EFI_ABORTED if the image is not supported. Additional details<br>
> >> + on why the image is not a supported image may be returned in AbortReason.<br>
> >> + - Validate the data from VendorCode if is not NULL. Firmware image<br>
> >> + validation must be performed before VendorCode data validation.<br>
> >> + VendorCode data is ignored or considered invalid if image validation<br>
> >> + fails. Return EFI_ABORTED if the VendorCode data is invalid.<br>
> >> +<br>
> >> + VendorCode enables vendor to implement vendor-specific firmware image update<br>
> >> + policy. Null if the caller did not specify the policy or use the default<br>
> >> + policy. As an example, vendor can implement a policy to allow an option to<br>
> >> + force a firmware image update when the abort reason is due to the new firmware<br>
> >> + image version is older than the current firmware image version or bad image<br>
> >> + checksum. Sensitive operations such as those wiping the entire firmware image<br>
> >> + and render the device to be non-functional should be encoded in the image<br>
> >> + itself rather than passed with the VendorCode. AbortReason enables vendor to<br>
> >> + have the option to provide a more detailed description of the abort reason to<br>
> >> + the caller.<br>
> >> +<br>
> >> + @param[in] Image Points to the new firmware image.<br>
> >> + @param[in] ImageSize Size, in bytes, of the new firmware image.<br>
> >> + @param[in] VendorCode This enables vendor to implement vendor-specific<br>
> >> + firmware image update policy. NULL indicates<br>
> >> + the caller did not specify the policy or use the<br>
> >> + default policy.<br>
> >> + @param[in] Progress A function used to report the progress of<br>
> >> + updating the firmware device with the new<br>
> >> + firmware image.<br>
> >> + @param[in] CapsuleFwVersion The version of the new firmware image from the<br>
> >> + update capsule that provided the new firmware<br>
> >> + image.<br>
> >> + @param[out] AbortReason A pointer to a pointer to a Null-terminated<br>
> >> + Unicode string providing more details on an<br>
> >> + aborted operation. The buffer is allocated by<br>
> >> + this function with<br>
> >> + EFI_BOOT_SERVICES.AllocatePool(). It is the<br>
> >> + caller's responsibility to free this buffer with<br>
> >> + EFI_BOOT_SERVICES.FreePool().<br>
> >> + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt<br>
> >> + status to report back to the ESRT table in case<br>
> >> + of error. This value will only be checked when this<br>
> >> + function returns an error.<br>
> >> +<br>
> >> + The return status code must fall in the range of<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.<br>
> >> +<br>
> >> + If the value falls outside this range, it will be converted<br>
> >> + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.<br>
> >> +<br>
> >> + @retval EFI_SUCCESS The firmware device was successfully updated<br>
> >> + with the new firmware image.<br>
> >> + @retval EFI_ABORTED The operation is aborted. Additional details<br>
> >> + are provided in AbortReason.<br>
> >> + @retval EFI_INVALID_PARAMETER The Image was NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER LastAttemptStatus was NULL.<br>
> >> + @retval EFI_UNSUPPORTED The operation is not supported.<br>
> >> +<br>
> >> +**/<br>
> >> +EFI_STATUS<br>
> >> +EFIAPI<br>
> >> +FmpDeviceSetImageWithStatus (<br>
> >> + IN CONST VOID *Image,<br>
> >> + IN UINTN ImageSize,<br>
> >> + IN CONST VOID *VendorCode, OPTIONAL<br>
> >> + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL<br>
> >> + IN UINT32 CapsuleFwVersion,<br>
> >> + OUT CHAR16 **AbortReason,<br>
> >> + OUT UINT32 *LastAttemptStatus<br>
> >> + )<br>
> >> +{<br>
> >> + EFI_STATUS Status = EFI_SUCCESS;<br>
> >> + UINT32 Updateable = 0;<br>
> >> +<br>
> >> + Status = FmpDeviceCheckImageWithStatus (Image, ImageSize, &Updateable, LastAttemptStatus);<br>
> >> + if (EFI_ERROR(Status))<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "SetImageWithStatus - Check Image failed with %r.\n", Status));<br>
> >> + goto cleanup;<br>
> >> + }<br>
> >> +<br>
> >> + if (Updateable != IMAGE_UPDATABLE_VALID)<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "SetImageWithStatus - Check Image returned that the Image was not valid for update.<br>
> >> Updatable value = 0x%X.\n", Updateable));<br>
> >> + Status = EFI_ABORTED;<br>
> >> + goto cleanup;<br>
> >> + }<br>
> >> +<br>
> >> + if (Progress == NULL)<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "SetImageWithStatus - Invalid progress callback\n"));<br>
> >> + Status = EFI_INVALID_PARAMETER;<br>
> >> + goto cleanup;<br>
> >> + }<br>
> >> +<br>
> >> + Status = Progress(15);<br>
> >> + if (EFI_ERROR(Status))<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "SetImageWithStatus - Progress Callback failed with Status %r.\n", Status));<br>
> >> + }<br>
> >> +<br>
> >> + {<br>
> >> + UINTN p;<br>
> >> +<br>
> >> + for (p = 20; p < 100; p++) {<br>
> >> + gBS->Stall (100000); //us = 0.1 seconds<br>
> >> + Progress (p);<br>
> >> + }<br>
> >> + }<br>
> >> +<br>
> >> + //TODO: add support for VendorCode, and AbortReason<br>
> >> +cleanup:<br>
> >> + if (EFI_ERROR (Status)) {<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + }<br>
> >> +<br>
> >> + return Status;<br>
> >> +}// SetImageWithStatus()<br>
> >> +<br>
> >> +<br>
> >> /**<br>
> >> Updates the firmware image of the device.<br>
> >><br>
> >> @@ -396,51 +523,98 @@ IN UINT32 CapsuleFwVersion,<br>
> >> OUT CHAR16 **AbortReason<br>
> >> )<br>
> >> {<br>
> >> - EFI_STATUS Status = EFI_SUCCESS;<br>
> >> - UINT32 Updateable = 0;<br>
> >> -<br>
> >> - Status = FmpDeviceCheckImage(Image, ImageSize, &Updateable);<br>
> >> - if (EFI_ERROR(Status))<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "SetImage - Check Image failed with %r.\n", Status));<br>
> >> - goto cleanup;<br>
> >> - }<br>
> >> -<br>
> >> - if (Updateable != IMAGE_UPDATABLE_VALID)<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "SetImage - Check Image returned that the Image was not valid for update. Updatable value<br>
> =<br>
> >> 0x%X.\n", Updateable));<br>
> >> - Status = EFI_ABORTED;<br>
> >> - goto cleanup;<br>
> >> - }<br>
> >> -<br>
> >> - if (Progress == NULL)<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "SetImage - Invalid progress callback\n"));<br>
> >> - Status = EFI_INVALID_PARAMETER;<br>
> >> - goto cleanup;<br>
> >> - }<br>
> >> -<br>
> >> - Status = Progress(15);<br>
> >> - if (EFI_ERROR(Status))<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "SetImage - Progress Callback failed with Status %r.\n", Status));<br>
> >> - }<br>
> >> -<br>
> >> - {<br>
> >> - UINTN p;<br>
> >> -<br>
> >> - for (p = 20; p < 100; p++) {<br>
> >> - gBS->Stall (100000); //us = 0.1 seconds<br>
> >> - Progress (p);<br>
> >> - }<br>
> >> - }<br>
> >> -<br>
> >> - //TODO: add support for VendorCode, and AbortReason<br>
> >> -cleanup:<br>
> >> - return Status;<br>
> >> + UINT32 LastAttemptStatus;<br>
> >> +<br>
> >> + return FmpDeviceSetImageWithStatus (<br>
> >> + Image,<br>
> >> + ImageSize,<br>
> >> + VendorCode,<br>
> >> + Progress,<br>
> >> + CapsuleFwVersion,<br>
> >> + AbortReason,<br>
> >> + &LastAttemptStatus<br>
> >> + );<br>
> >> }// SetImage()<br>
> >><br>
> >><br>
> >> +/**<br>
> >> + Checks if a new firmware image is valid for the firmware device. This<br>
> >> + function allows firmware update operation to validate the firmware image<br>
> >> + before FmpDeviceSetImage() is called.<br>
> >> +<br>
> >> + @param[in] Image Points to a new firmware image.<br>
> >> + @param[in] ImageSize Size, in bytes, of a new firmware image.<br>
> >> + @param[out] ImageUpdatable Indicates if a new firmware image is valid for<br>
> >> + a firmware update to the firmware device. The<br>
> >> + following values from the Firmware Management<br>
> >> + Protocol are supported:<br>
> >> + IMAGE_UPDATABLE_VALID<br>
> >> + IMAGE_UPDATABLE_INVALID<br>
> >> + IMAGE_UPDATABLE_INVALID_TYPE<br>
> >> + IMAGE_UPDATABLE_INVALID_OLD<br>
> >> + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE<br>
> >> + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt<br>
> >> + status to report back to the ESRT table in case<br>
> >> + of error. This value will only be checked when this<br>
> >> + function returns an error.<br>
> >> +<br>
> >> + The return status code must fall in the range of<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to<br>
> >> + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.<br>
> >> +<br>
> >> + If the value falls outside this range, it will be converted<br>
> >> + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.<br>
> >> +<br>
> >> + @retval EFI_SUCCESS The image was successfully checked. Additional<br>
> >> + status information is returned in<br>
> >> + ImageUpdatable.<br>
> >> + @retval EFI_INVALID_PARAMETER Image is NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.<br>
> >> + @retval EFI_INVALID_PARAMETER LastAttemptStatus is NULL.<br>
> >> +<br>
> >> +**/<br>
> >> +EFI_STATUS<br>
> >> +EFIAPI<br>
> >> +FmpDeviceCheckImageWithStatus (<br>
> >> + IN CONST VOID *Image,<br>
> >> + IN UINTN ImageSize,<br>
> >> + OUT UINT32 *ImageUpdatable,<br>
> >> + OUT UINT32 *LastAttemptStatus<br>
> >> + )<br>
> >> +{<br>
> >> + EFI_STATUS status = EFI_SUCCESS;<br>
> >> +<br>
> >> + if (LastAttemptStatus == NULL) {<br>
> >> + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer Parameter is NULL.\n"));<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;<br>
> >> +<br>
> >> + if (ImageUpdatable == NULL)<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Parameter is NULL.\n"));<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + status = EFI_INVALID_PARAMETER;<br>
> >> + goto cleanup;<br>
> >> + }<br>
> >> +<br>
> >> + //<br>
> >> + //Set to valid and then if any tests fail it will update this flag.<br>
> >> + //<br>
> >> + *ImageUpdatable = IMAGE_UPDATABLE_VALID;<br>
> >> +<br>
> >> + if (Image == NULL)<br>
> >> + {<br>
> >> + DEBUG((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter is NULL.\n"));<br>
> >> + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; //not sure if this is needed<br>
> >> + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;<br>
> >> + return EFI_INVALID_PARAMETER;<br>
> >> + }<br>
> >> +<br>
> >> +cleanup:<br>
> >> + return status;<br>
> >> +}// CheckImageWithStatus()<br>
> >> +<br>
> >><br>
> >> /**<br>
> >> Checks if the firmware image is valid for the device.<br>
> >> @@ -465,29 +639,9 @@ IN UINTN ImageSize,<br>
> >> OUT UINT32 *ImageUpdateable<br>
> >> )<br>
> >> {<br>
> >> - EFI_STATUS status = EFI_SUCCESS;<br>
> >> + UINT32 LastAttemptStatus;<br>
> >><br>
> >> - if (ImageUpdateable == NULL)<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "CheckImage - ImageUpdateable Pointer Parameter is NULL.\n"));<br>
> >> - status = EFI_INVALID_PARAMETER;<br>
> >> - goto cleanup;<br>
> >> - }<br>
> >> -<br>
> >> - //<br>
> >> - //Set to valid and then if any tests fail it will update this flag.<br>
> >> - //<br>
> >> - *ImageUpdateable = IMAGE_UPDATABLE_VALID;<br>
> >> -<br>
> >> - if (Image == NULL)<br>
> >> - {<br>
> >> - DEBUG((DEBUG_ERROR, "CheckImage - Image Pointer Parameter is NULL.\n"));<br>
> >> - *ImageUpdateable = IMAGE_UPDATABLE_INVALID; //not sure if this is needed<br>
> >> - return EFI_INVALID_PARAMETER;<br>
> >> - }<br>
> >> -<br>
> >> -cleanup:<br>
> >> - return status;<br>
> >> + return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdateable, &LastAttemptStatus);<br>
> >> }// CheckImage()<br>
> >><br>
> >> /**<br>
> >> --<br>
> >> 2.28.0.windows.1<br>
> ><br>
<br>
<br style="mso-special-character:line-break">
<![if !supportLineBreakNewLine]><br style="mso-special-character:line-break">
<![endif]><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal"></o:p></span></p>
</div>
</div>
</body>
</html>
<div width="1" style="color:white;clear:both">_._,_._,_</div> <hr> Groups.io Links:<p> You receive all messages sent to this group. <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/67293">View/Reply Online (#67293)</a> | | <a target="_blank" href="https://groups.io/mt/77251053/1813853">Mute This Topic</a> | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br> <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> | <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a> [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>