soc/intel/common/basecode: Implement CSE update flow
The following changes are done in this patch: 1. Get the CSE partition info containing version of CSE RW using GET_BOOT_PARTITION_INFO HECI command 2. Get the me_rw.version from the currently selected RW slot. 3. If the versions from the above 2 locations don't match start the update - If CSE's current boot partition is not RO, then * Set the CSE's next boot partition to RO using SET_BOOT_PARTITION HECI command. * Send global reset command to reset the system. - Enable HMRFPO (Host ME Region Flash Protection Override) operation mode using HMRFPO_ENABLE HECI command - Erase and Copy the CBFS CSE RW to CSE RW partition - Set the CSE's next boot partition to RW using SET_BOOT_PARTITION HECI command - Trigger global reset - The system should boot with the updated CSE RW partition. TEST=Verified basic update flows on hatch and helios. BUG=b:111330995 Change-Id: I12f6bba3324069d65edabaccd234006b0840e700 Signed-off-by: Rizwan Qureshi <rizwan.qureshi@intel.com> Signed-off-by: Sridhar Siricilla <sridhar.siricilla@intel.com> Signed-off-by: V Sowmya <v.sowmya@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/35403 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
56642930ab
commit
ec321094f6
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by Microsoft Visio, SVG Export Layout_after.svg Page-1 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
|
||||
width="2.39231in" height="2.05998in" viewBox="0 0 172.246 148.318" xml:space="preserve" color-interpolation-filters="sRGB"
|
||||
class="st12">
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.st1 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st2 {fill:#000000;font-family:Calibri;font-size:0.333344em}
|
||||
.st3 {fill:#ffc000;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st4 {fill:#000000;font-family:Calibri;font-size:0.499992em}
|
||||
.st5 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st6 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
|
||||
.st7 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st8 {stroke:#4bacc6;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st9 {font-size:1em}
|
||||
.st10 {marker-end:url(#mrkr4-59);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st11 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.22935779816514}
|
||||
.st12 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
|
||||
]]>
|
||||
</style>
|
||||
|
||||
<defs id="Markers">
|
||||
<g id="lend4">
|
||||
<path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/>
|
||||
</g>
|
||||
<marker id="mrkr4-59" class="st11" refX="-8.72" orient="auto" markerUnits="strokeWidth" overflow="visible">
|
||||
<use xlink:href="#lend4" transform="scale(-4.36,-4.36) "/>
|
||||
</marker>
|
||||
</defs>
|
||||
<g>
|
||||
<title>Page-1</title>
|
||||
<g id="shape116-1" transform="translate(38.7567,-139.932)">
|
||||
<title>Rectangle.116</title>
|
||||
<desc>DESC</desc>
|
||||
<rect x="0" y="143.783" width="79.3701" height="4.53543" class="st1"/>
|
||||
<text x="35.49" y="147.25" class="st2">DESC</text> </g>
|
||||
<g id="shape117-4" transform="translate(38.7567,-130.935)">
|
||||
<title>Rectangle.117</title>
|
||||
<desc>CSE - RO</desc>
|
||||
<rect x="0" y="139.605" width="79.3701" height="8.71293" class="st3"/>
|
||||
<text x="29.35" y="145.76" class="st4">CSE - RO</text> </g>
|
||||
<g id="shape118-7" transform="translate(38.5344,-4.54823)">
|
||||
<title>Rectangle.118</title>
|
||||
<rect x="0" y="29.8973" width="79.5923" height="118.421" class="st1"/>
|
||||
</g>
|
||||
<g id="shape119-9" transform="translate(41.225,-5.80807)">
|
||||
<title>Rectangle.119</title>
|
||||
<desc>COREBOOT_RO</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st5"/>
|
||||
<text x="18.32" y="135.95" class="st4">COREBOOT_RO</text> </g>
|
||||
<g id="shape120-12" transform="translate(41.225,-34.1545)">
|
||||
<title>Rectangle.120</title>
|
||||
<desc>RW_MISC</desc>
|
||||
<rect x="0" y="143.907" width="74.3581" height="4.41113" class="st5"/>
|
||||
<text x="29.12" y="147.31" class="st2">RW_MISC</text> </g>
|
||||
<g id="shape121-15" transform="translate(41.225,-38.7215)">
|
||||
<title>Rectangle.121</title>
|
||||
<desc>FW_MAIN_B</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st6"/>
|
||||
<text x="21.52" y="129.37" class="st4">FW_MAIN_B</text> </g>
|
||||
<g id="shape122-18" transform="translate(41.225,-67.0679)">
|
||||
<title>Rectangle.122</title>
|
||||
<desc>FW_MAIN_A</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st6"/>
|
||||
<text x="21.41" y="129.37" class="st4">FW_MAIN_A</text> </g>
|
||||
<g id="shape123-21" transform="translate(3.88308,-0.375)">
|
||||
<title>Sheet.123</title>
|
||||
<desc>0x1FFFFFF</desc>
|
||||
<rect x="0" y="137.688" width="41.4007" height="10.6299" class="st7"/>
|
||||
<text x="8.09" y="144.8" class="st4">0x1FFFFFF</text> </g>
|
||||
<g id="shape124-24" transform="translate(21.7488,-138.564)">
|
||||
<title>Sheet.124</title>
|
||||
<desc>0x0</desc>
|
||||
<rect x="0" y="138.939" width="21.2598" height="9.37934" class="st7"/>
|
||||
<text x="6.29" y="145.43" class="st4">0x0</text> </g>
|
||||
<g id="shape125-27" transform="translate(41.2627,-96.0443)">
|
||||
<title>Rectangle.125</title>
|
||||
<desc>RW_LEGACY</desc>
|
||||
<rect x="0" y="122.448" width="74.3581" height="25.8706" class="st5"/>
|
||||
<text x="27.04" y="136.58" class="st2">RW_LEGACY</text> </g>
|
||||
<g id="shape126-30" transform="translate(119.253,-6.75295)">
|
||||
<title>Right Brace.126</title>
|
||||
<path d="M-0 148.32 A9.42279 2.96575 -180 0 0 5.11 146.6 L5.11 135.46 L10.21 135.46 L5.11 135.46 L5.11 124.32 A9.42279
|
||||
2.96575 -180 0 0 0 122.6" class="st8"/>
|
||||
</g>
|
||||
<g id="shape127-33" transform="translate(120.961,-10.2963)">
|
||||
<title>Sheet.127</title>
|
||||
<desc>HW WP</desc>
|
||||
<rect x="0" y="137.688" width="31.1811" height="10.6299" class="st7"/>
|
||||
<text x="6.16" y="144.8" class="st4">HW WP</text> </g>
|
||||
<g id="shape128-36" transform="translate(119.43,-123.061)">
|
||||
<title>Right Brace.128</title>
|
||||
<path d="M-0 148.32 a10.4615 0.900102 -180 0 0 5.66929 -0.520272 L5.67 144.42 L11.34 144.42 L5.67 144.42 L5.67 141.03
|
||||
a10.4615 0.900102 -180 0 0 -5.66929 -0.520272" class="st8"/>
|
||||
</g>
|
||||
<g id="shape129-39" transform="translate(126.517,-119.597)">
|
||||
<title>Sheet.129</title>
|
||||
<desc>SPI Controller WP via descriptor</desc>
|
||||
<rect x="0" y="138.043" width="45.3543" height="10.2756" class="st7"/>
|
||||
<text x="5.53" y="141.98" class="st2">SPI Controller WP via <tspan x="14.37" dy="1.2em" class="st9">descriptor</tspan></text> </g>
|
||||
<g id="group130-43" transform="translate(42.8947,-77.0772)">
|
||||
<title>Sheet.130</title>
|
||||
<g id="shape131-44">
|
||||
<title>Rectangle.423</title>
|
||||
<desc>CSE-RW</desc>
|
||||
<rect x="0" y="141.232" width="70.8661" height="7.08661" class="st3"/>
|
||||
<text x="25.77" y="146.58" class="st4">CSE-RW</text> </g>
|
||||
</g>
|
||||
<g id="group132-47" transform="translate(42.8947,-48.7307)">
|
||||
<title>Sheet.132</title>
|
||||
<g id="shape133-48">
|
||||
<title>Rectangle.423</title>
|
||||
<desc>CSE-RW</desc>
|
||||
<rect x="0" y="141.232" width="70.8661" height="7.08661" class="st3"/>
|
||||
<text x="25.77" y="146.58" class="st4">CSE-RW</text> </g>
|
||||
</g>
|
||||
<g id="shape134-51" transform="translate(38.6427,-123.114)">
|
||||
<title>Rectangle.134</title>
|
||||
<desc>CSE-RW</desc>
|
||||
<rect x="0" y="140.497" width="79.3701" height="7.82103" class="st3"/>
|
||||
<text x="30.03" y="146.21" class="st4">CSE-RW</text> </g>
|
||||
<g id="shape135-54" transform="translate(41.225,-52.8947)">
|
||||
<title>Universal connector.473</title>
|
||||
<path d="M0 148.32 L-8.38 148.32 A8.37776 8.37776 0 0 1 -16.76 139.94 L-16.76 111.25 L-16.76 81.27 A7.08661 7.08661 0
|
||||
0 1 -9.67 74.19 L-9.12 74.19" class="st10"/>
|
||||
</g>
|
||||
<g id="shape136-60" transform="translate(41.225,-81.2411)">
|
||||
<title>Universal connector.136</title>
|
||||
<path d="M0 148.32 L-8.38 148.32 A8.37776 8.37776 0 0 1 -16.76 139.94 L-16.76 125.43 L-16.76 109.62 A7.08661 7.08661
|
||||
0 0 1 -9.67 102.53 L-9.12 102.53" class="st10"/>
|
||||
</g>
|
||||
<g id="shape138-65" transform="translate(-124.557,86.8317) rotate(-90)">
|
||||
<title>Sheet.138</title>
|
||||
<desc>CSE RW copied during an update</desc>
|
||||
<rect x="0" y="124.932" width="58.1102" height="23.3858" class="st7"/>
|
||||
<text x="10.77" y="134.83" class="st4">CSE RW copied <tspan x="8.15" dy="1.2em" class="st9">during an update</tspan></text> </g>
|
||||
<g id="shape139-69" transform="translate(119.43,-133.052)">
|
||||
<title>Right Brace.139</title>
|
||||
<path d="M0 148.32 a10.4615 0.736641 -180 0 0 5.66929 -0.425789 L5.67 145.12 L11.34 145.12 L5.67 145.12 L5.67 142.36
|
||||
a10.4615 0.736641 -180 0 0 -5.66929 -0.425789" class="st8"/>
|
||||
</g>
|
||||
<g id="shape140-72" transform="translate(127.934,-133.061)">
|
||||
<title>Sheet.140</title>
|
||||
<desc>GRP0 Protected</desc>
|
||||
<rect x="0" y="140.523" width="35.4331" height="7.79528" class="st7"/>
|
||||
<text x="4.86" y="145.62" class="st2">GRP0 Protected</text> </g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.7 KiB |
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by Microsoft Visio, SVG Export Layout_before.svg Page-1 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
|
||||
width="2.3058in" height="2.05998in" viewBox="0 0 166.017 148.318" xml:space="preserve" color-interpolation-filters="sRGB"
|
||||
class="st11">
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.st1 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st2 {fill:#000000;font-family:Calibri;font-size:0.333344em}
|
||||
.st3 {fill:#ffc000;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st4 {fill:#000000;font-family:Calibri;font-size:0.499992em}
|
||||
.st5 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st6 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
|
||||
.st7 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st8 {stroke:#4bacc6;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st9 {fill:#000000;font-family:Calibri;font-size:0.416656em}
|
||||
.st10 {font-size:1em}
|
||||
.st11 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
|
||||
]]>
|
||||
</style>
|
||||
|
||||
<g>
|
||||
<title>Page-1</title>
|
||||
<g id="shape87-1" transform="translate(35.2486,-139.932)">
|
||||
<title>Rectangle.178</title>
|
||||
<desc>DESC</desc>
|
||||
<rect x="0" y="143.783" width="79.3701" height="4.53543" class="st1"/>
|
||||
<text x="35.49" y="147.25" class="st2">DESC</text> </g>
|
||||
<g id="shape88-4" transform="translate(35.2486,-122.945)">
|
||||
<title>Rectangle.179</title>
|
||||
<desc>CSME/PMC</desc>
|
||||
<rect x="0" y="131.615" width="79.3701" height="16.7031" class="st3"/>
|
||||
<text x="25.8" y="141.02" class="st4">CSME/PMC</text> </g>
|
||||
<g id="shape89-7" transform="translate(35.0263,-4.54823)">
|
||||
<title>Rectangle.180</title>
|
||||
<rect x="0" y="29.8973" width="79.5923" height="118.421" class="st1"/>
|
||||
</g>
|
||||
<g id="shape90-9" transform="translate(37.7169,-5.80807)">
|
||||
<title>Rectangle.181</title>
|
||||
<desc>COREBOOT_RO</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st5"/>
|
||||
<text x="18.32" y="135.95" class="st4">COREBOOT_RO</text> </g>
|
||||
<g id="shape91-12" transform="translate(37.7169,-34.1545)">
|
||||
<title>Rectangle.182</title>
|
||||
<desc>RW_MISC</desc>
|
||||
<rect x="0" y="143.907" width="74.3581" height="4.41113" class="st5"/>
|
||||
<text x="29.12" y="147.31" class="st2">RW_MISC</text> </g>
|
||||
<g id="shape92-15" transform="translate(37.7169,-38.7215)">
|
||||
<title>Rectangle.183</title>
|
||||
<desc>FW_MAIN_B</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st6"/>
|
||||
<text x="21.52" y="129.37" class="st4">FW_MAIN_B</text> </g>
|
||||
<g id="shape93-18" transform="translate(37.7169,-67.0679)">
|
||||
<title>Rectangle.184</title>
|
||||
<desc>FW_MAIN_A</desc>
|
||||
<rect x="0" y="119.972" width="74.3581" height="28.3465" class="st6"/>
|
||||
<text x="21.41" y="129.37" class="st4">FW_MAIN_A</text> </g>
|
||||
<g id="shape94-21" transform="translate(0.375,-0.375)">
|
||||
<title>Sheet.94</title>
|
||||
<desc>0x1FFFFFF</desc>
|
||||
<rect x="0" y="137.688" width="41.4007" height="10.6299" class="st7"/>
|
||||
<text x="8.09" y="144.8" class="st4">0x1FFFFFF</text> </g>
|
||||
<g id="shape95-24" transform="translate(18.2407,-138.564)">
|
||||
<title>Sheet.95</title>
|
||||
<desc>0x0</desc>
|
||||
<rect x="0" y="138.939" width="21.2598" height="9.37934" class="st7"/>
|
||||
<text x="6.29" y="145.43" class="st4">0x0</text> </g>
|
||||
<g id="shape106-27" transform="translate(37.7546,-96.0443)">
|
||||
<title>Rectangle.106</title>
|
||||
<desc>RW_LEGACY</desc>
|
||||
<rect x="0" y="122.448" width="74.3581" height="25.8706" class="st5"/>
|
||||
<text x="27.04" y="136.58" class="st2">RW_LEGACY</text> </g>
|
||||
<g id="shape113-30" transform="translate(115.744,-6.75295)">
|
||||
<title>Right Brace.398</title>
|
||||
<path d="M-0 148.32 A9.42279 2.96575 -180 0 0 5.11 146.6 L5.11 135.46 L10.21 135.46 L5.11 135.46 L5.11 124.32 A9.42279
|
||||
2.96575 -180 0 0 0 122.6" class="st8"/>
|
||||
</g>
|
||||
<g id="shape96-33" transform="translate(117.453,-10.2963)">
|
||||
<title>Sheet.96</title>
|
||||
<desc>HW WP</desc>
|
||||
<rect x="0" y="137.688" width="31.1811" height="10.6299" class="st7"/>
|
||||
<text x="6.16" y="144.8" class="st4">HW WP</text> </g>
|
||||
<g id="shape115-36" transform="translate(116.508,-123.131)">
|
||||
<title>Right Brace.115</title>
|
||||
<path d="M0 148.32 A10.4615 2.27029 -180 0 0 5.67 147.01 L5.67 138.48 L11.34 138.48 L5.67 138.48 L5.67 129.95 A10.4615
|
||||
2.27029 -180 0 0 0 128.63" class="st8"/>
|
||||
</g>
|
||||
<g id="shape97-39" transform="translate(120.288,-122.265)">
|
||||
<title>Sheet.97</title>
|
||||
<desc>SPI Controller WP via descriptor</desc>
|
||||
<rect x="0" y="124.932" width="45.3543" height="23.3858" class="st7"/>
|
||||
<text x="4.71" y="135.13" class="st9">SPI Controller WP <tspan x="8.83" dy="1.2em" class="st10">via descriptor</tspan></text> </g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.0 KiB |
|
@ -0,0 +1,127 @@
|
|||
CSE FW update mechanism for devices in field
|
||||
|
||||
## Introduction
|
||||
|
||||
CSE Firmware and PMC Firmware are critical components of Intel SoCs.
|
||||
CSE and PMC cooperate by providing platform services during boot and other
|
||||
power transition flows.
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Currently, on Chromium OS Systems, CSE region is not updatable. So, new CSE FW
|
||||
versions that are released by Intel to address important functional and security
|
||||
bugs post-product launch will not be available to the end-user. Hence, the proposed
|
||||
solution allows in-field CSE FW update to propagate those bug fixes
|
||||
to end user platforms.
|
||||
|
||||
## Design Proposal
|
||||
|
||||
### CSE FW design Proposal:
|
||||
|
||||
Key Elements:
|
||||
|
||||
- CSE FW layout is composed of two bootable partitions (RO Recovery Partition
|
||||
and RW Normal Partition).
|
||||
|
||||
- Boot partition selection: An API-based mechanism is used to decide from which partition
|
||||
CSE will boot.
|
||||
|
||||
- The HECI APIs below will be supported in this CSE FW:
|
||||
|
||||
- HMRFPO_ENABLE: This command requests the CSE enter a mode in which writes to
|
||||
the CSE region from the CSE are disabled. It also grants temporary write access
|
||||
to the RW partition from the host (RO is still protected by GPR0).
|
||||
|
||||
- GET_PARTITION_INFO: The command retrieves information for each boot partition from CSE
|
||||
like version, start/end offsets of a partition within CSE region, and boot
|
||||
partition status. Also, it provides below information:
|
||||
- The current boot partition which was used during this boot,
|
||||
- The boot partition that will be used on the next CSE reset
|
||||
- The number of boot partitions available in the CSE region
|
||||
|
||||
- SET_BOOT_PARTITION_INFO: This command allows the firmware to request the
|
||||
CSE to boot from either its RO or RW partition at its next reset.
|
||||
|
||||
- DATA_CLEAR: This command requests the CSE to reset its data partition back
|
||||
to manufacturing defaults
|
||||
|
||||
FW Layout, RW/RO Partitions:
|
||||
|
||||
The CSE RO partition is the first in the CSE boot order, hence it will be used
|
||||
out of G3. RO partition contains minimum CSE code capable to boot platform and
|
||||
execute FW update of RW partition. In addition to CSE code, the RO partition also
|
||||
contains PMC FW patch and other CSE-loadable platform FW components.
|
||||
|
||||
RW partition contains fully operational CSE FW, PMC FW, other CSE loadable
|
||||
platform FW components.
|
||||
|
||||
Boot partition selection:
|
||||
|
||||
CSE FW shall support 2 APIs to get boot partition info, and set boot partition
|
||||
info to notify CSE to select the partition on the next boot.
|
||||
|
||||
### HOST FW Design proposal:
|
||||
|
||||
Key Elements:
|
||||
|
||||
- Build time artifacts:
|
||||
|
||||
CSE RW Version update binary - The FW shall pack CSE RW update blob and
|
||||
corresponding version binary which contains version of the CSE RW blob.
|
||||
|
||||
- FW Update:
|
||||
|
||||
coreboot will implement the logic to compare the CSE's FW version with CBFS
|
||||
CSE RW binary's version in the firmware slot (FW_MAIN_A/FW_MAIN_B) and update
|
||||
the CSE RW region if there is a version mismatch. If there is no version
|
||||
mismatch, firmware skips CSE FW update.
|
||||
|
||||
- Handling of CSE FW Downgrade:
|
||||
|
||||
coreboot will send DATA_CLEAR HECI command when there is a CSE FW downgrade.
|
||||
This must be done to avoid data mismatch due to CSE FW downgrade. Further,
|
||||
CSE will restore the data back to manufacturing defaults after data reset.
|
||||
|
||||
|
||||
## Implementation Details
|
||||
|
||||
|
||||
To enable CSE FW update flow the following changes are required in coreboot:
|
||||
|
||||
* Descriptor change may be required to accommodate CSE binary. The CSE binary is tied with
|
||||
a platform. So CSE size may vary from one platform to another.
|
||||
* FMAP changes may be required to accommodate CSE binary and CSE RW blob in the RW CBFS region.
|
||||
Please check platform specific CSE kit for CSE binary information.
|
||||
* CSE Lite SKU binary and CSE RW blob
|
||||
* Makefile change to pack CSE RW binaries in the CBFS
|
||||
* Implementation of update flow:
|
||||
- Get CSE boot partition info using GET_BOOT_PARTITION_INFO HECI command.
|
||||
- Get the cbfs_me_rw.version from the currently selected RW slot.
|
||||
- If the version from the above 2 locations don't match, then start CSE FW update.
|
||||
- If CSE is not booting from RO, then
|
||||
- Set the CSE's next boot partition to RO using SET_BOOT_PARTITION_INFO
|
||||
HECI command.
|
||||
- Send GLOBAL_RESET HECI command to reset the system.
|
||||
- If RW update is a CSE FW downgrade, then coreboot has to send
|
||||
DATA_CLEAR command to clear run time data of CSE.
|
||||
- Enable HMRFPO Mode (Host ME Region Flash Protection Override) by
|
||||
sending HMRFPO_ENABLE HECI command to CSE.
|
||||
- Erase and Copy the CBFS CSE RW to CSE RW partition
|
||||
- Set CSE's next boot partition to RW.
|
||||
- Trigger Global Reset which resets both CSE and Host.
|
||||
Then system should boot with the updated CSE.
|
||||
|
||||
* The resulting flash layout is shown below:
|
||||
|
||||
![Flash Layout](./Layout_before.svg) ![FlashLayout](./Layout_after.svg)
|
||||
|
||||
|
||||
- Typical boot flow
|
||||
|
||||
- Vboot selects the RW FW (FW_MAIN_A or FW_MAIN_B) to boot.
|
||||
- coreboot skips CSE FW update flow if boot mode is recovery.
|
||||
- If CSE RW blob is not locatable in the CBFS, then RW Firmware skips update flow
|
||||
and sends SET_BOOT_PARTITION_INFO command to switch CSE to boot from RW
|
||||
and issues Global Reset if CSE is already not booting from RW partition.
|
||||
- The RW firmware will compare the CSE RW version with CSE RW blob in the slot.
|
||||
- If there is a mismatch, then firmware will carry out update flow as explained before.
|
|
@ -10,3 +10,4 @@ This section contains documentation about coreboot on specific Intel SOCs.
|
|||
- [MP Initialization](mp_init/mp_init.md)
|
||||
- [Firmware Interface Table](fit.md)
|
||||
- [Apollolake](apollolake/index.md)
|
||||
- [CSE FW Update](cse_fw_update/cse_fw_update_model.md)
|
||||
|
|
|
@ -19,3 +19,15 @@ config SOC_INTEL_CSE_LITE_SKU
|
|||
depends on CHROMEOS
|
||||
help
|
||||
Enables CSE Lite SKU
|
||||
|
||||
config SOC_INTEL_CSE_FMAP_NAME
|
||||
string "Name of CSE Region in FMAP"
|
||||
default "SI_ME"
|
||||
help
|
||||
Name of CSE region in FMAP
|
||||
|
||||
config SOC_INTEL_CSE_RW_CBFS_NAME
|
||||
string "CBFS entry name for CSE RW blob"
|
||||
default "me_rw"
|
||||
help
|
||||
CBFS entry name for Intel CSE CBFS RW blob
|
||||
|
|
|
@ -1,15 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#include <bootstate.h>
|
||||
#include <console/console.h>
|
||||
#include <soc/intel/common/reset.h>
|
||||
#include <boot_device.h>
|
||||
#include <cbfs.h>
|
||||
#include <commonlib/cbfs.h>
|
||||
#include <commonlib/region.h>
|
||||
#include <fmap.h>
|
||||
#include <intelblocks/cse.h>
|
||||
#include <lib.h>
|
||||
#include <security/vboot/vboot_common.h>
|
||||
#include <security/vboot/misc.h>
|
||||
#include <vb2_api.h>
|
||||
#include <soc/intel/common/reset.h>
|
||||
|
||||
/* CSE RW version size reserved in the CSE CBFS RW binary */
|
||||
#define CSE_RW_VERSION_SZ 16
|
||||
|
||||
/* Converts bp index to boot partition string */
|
||||
#define GET_BP_STR(bp_index) (bp_index ? "RW" : "RO")
|
||||
|
||||
/* CSE RW boot partition signature */
|
||||
#define CSE_RW_SIGNATURE 0x000055aa
|
||||
|
||||
/* CSE RW boot partition signature size */
|
||||
#define CSE_RW_SIGN_SIZE sizeof(uint32_t)
|
||||
|
||||
/*
|
||||
* CSE Firmware supports 3 boot partitions. For CSE Lite SKU, only 2 boot partitions are
|
||||
* used and 3rd boot partition is set to BP_STATUS_PARTITION_NOT_PRESENT.
|
||||
|
@ -22,10 +37,10 @@
|
|||
|
||||
/* CSE Lite SKU's valid bootable partition identifiers */
|
||||
enum boot_partition_id {
|
||||
/* RO(BP1) contains recovery/minimal boot FW */
|
||||
/* RO(BP1) contains recovery/minimal boot firmware */
|
||||
RO = 0,
|
||||
|
||||
/* RW(BP2) contains fully functional CSE Firmware */
|
||||
/* RW(BP2) contains fully functional CSE firmware */
|
||||
RW = 1
|
||||
};
|
||||
|
||||
|
@ -162,6 +177,49 @@ static const struct cse_bp_entry *cse_get_bp_entry(enum boot_partition_id bp,
|
|||
return &cse_bp_info->bp_entries[bp];
|
||||
}
|
||||
|
||||
static void cse_get_bp_entry_range(const struct cse_bp_info *cse_bp_info,
|
||||
enum boot_partition_id bp, uint32_t *start_offset, uint32_t *end_offset)
|
||||
{
|
||||
const struct cse_bp_entry *cse_bp;
|
||||
|
||||
cse_bp = cse_get_bp_entry(bp, cse_bp_info);
|
||||
|
||||
if (start_offset)
|
||||
*start_offset = cse_bp->start_offset;
|
||||
|
||||
if (end_offset)
|
||||
*end_offset = cse_bp->end_offset;
|
||||
|
||||
}
|
||||
|
||||
static const struct fw_version *cse_get_bp_entry_version(enum boot_partition_id bp,
|
||||
const struct cse_bp_info *bp_info)
|
||||
{
|
||||
const struct cse_bp_entry *cse_bp;
|
||||
|
||||
cse_bp = cse_get_bp_entry(bp, bp_info);
|
||||
return &cse_bp->fw_ver;
|
||||
}
|
||||
|
||||
static const struct fw_version *cse_get_rw_version(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
return cse_get_bp_entry_version(RW, cse_bp_info);
|
||||
}
|
||||
|
||||
static bool cse_is_rw_bp_status_valid(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
const struct cse_bp_entry *rw_bp;
|
||||
|
||||
rw_bp = cse_get_bp_entry(RW, cse_bp_info);
|
||||
|
||||
if (rw_bp->status == BP_STATUS_PARTITION_NOT_PRESENT ||
|
||||
rw_bp->status == BP_STATUS_GENERAL_FAILURE) {
|
||||
printk(BIOS_ERR, "cse_lite: RW BP (status:%u) is not valid\n", rw_bp->status);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
const struct cse_bp_entry *cse_bp;
|
||||
|
@ -196,6 +254,9 @@ static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info)
|
|||
* - When CSE boots from RW partition (COM: Normal and CWS: Normal)
|
||||
* - When CSE boots from RO partition (COM: Soft Temp Disable and CWS: Normal)
|
||||
* - After HMRFPO_ENABLE command is issued to CSE (COM: SECOVER_MEI_MSG and CWS: Normal)
|
||||
* The prerequisite check should be handled in cse_get_bp_info() and
|
||||
* cse_set_next_boot_partition() since the CSE's current operation mode is changed between these
|
||||
* cmd handler calls.
|
||||
*/
|
||||
static bool cse_is_bp_cmd_info_possible(void)
|
||||
{
|
||||
|
@ -294,40 +355,259 @@ static bool cse_set_next_boot_partition(enum boot_partition_id bp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cse_boot_to_rw(const struct cse_bp_info *cse_bp_info)
|
||||
/* Set the CSE's next boot partition and issues system reset */
|
||||
static bool cse_set_and_boot_from_next_bp(enum boot_partition_id bp)
|
||||
{
|
||||
if (cse_get_current_bp(cse_bp_info) == RW)
|
||||
return true;
|
||||
|
||||
if (!cse_set_next_boot_partition(RW))
|
||||
if (!cse_set_next_boot_partition(bp))
|
||||
return false;
|
||||
|
||||
do_global_reset();
|
||||
|
||||
die("cse_lite: Failed to reset system\n");
|
||||
die("cse_lite: Failed to reset the system\n");
|
||||
|
||||
/* Control never reaches here */
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool cse_is_rw_status_valid(const struct cse_bp_info *cse_bp_info)
|
||||
static bool cse_boot_to_rw(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
const struct cse_bp_entry *rw_bp;
|
||||
if (cse_get_current_bp(cse_bp_info) == RW)
|
||||
return true;
|
||||
|
||||
/* RW(BP2) alone represents RW partition */
|
||||
rw_bp = cse_get_bp_entry(RW, cse_bp_info);
|
||||
return cse_set_and_boot_from_next_bp(RW);
|
||||
}
|
||||
|
||||
if (rw_bp->status == BP_STATUS_PARTITION_NOT_PRESENT ||
|
||||
rw_bp->status == BP_STATUS_GENERAL_FAILURE) {
|
||||
printk(BIOS_ERR, "cse_lite: RW BP (status:%u) is not valid\n", rw_bp->status);
|
||||
static bool cse_boot_to_ro(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
if (cse_get_current_bp(cse_bp_info) == RO)
|
||||
return true;
|
||||
|
||||
return cse_set_and_boot_from_next_bp(RO);
|
||||
}
|
||||
|
||||
static bool cse_get_rw_rdev(struct region_device *rdev)
|
||||
{
|
||||
if (fmap_locate_area_as_rdev_rw(CONFIG_SOC_INTEL_CSE_FMAP_NAME, rdev) < 0) {
|
||||
printk(BIOS_ERR, "cse_lite: Failed to locate %s in FMAP\n",
|
||||
CONFIG_SOC_INTEL_CSE_FMAP_NAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_get_cbfs_rdev(struct region_device *source_rdev)
|
||||
{
|
||||
struct cbfsf file_desc;
|
||||
|
||||
if (cbfs_boot_locate(&file_desc, CONFIG_SOC_INTEL_CSE_RW_CBFS_NAME, NULL) < 0)
|
||||
return false;
|
||||
|
||||
cbfs_file_data(source_rdev, &file_desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_is_rw_bp_sign_valid(const struct region_device *target_rdev)
|
||||
{
|
||||
uint32_t cse_bp_sign;
|
||||
|
||||
if (rdev_readat(target_rdev, &cse_bp_sign, 0, CSE_RW_SIGN_SIZE) != CSE_RW_SIGN_SIZE) {
|
||||
printk(BIOS_ERR, "cse_lite: Failed to read RW boot partition signature\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return cse_bp_sign == CSE_RW_SIGNATURE;
|
||||
}
|
||||
|
||||
static bool cse_get_target_rdev(const struct cse_bp_info *cse_bp_info,
|
||||
struct region_device *target_rdev)
|
||||
{
|
||||
struct region_device cse_region_rdev;
|
||||
size_t size;
|
||||
uint32_t start_offset;
|
||||
uint32_t end_offset;
|
||||
|
||||
if (!cse_get_rw_rdev(&cse_region_rdev))
|
||||
return false;
|
||||
|
||||
cse_get_bp_entry_range(cse_bp_info, RW, &start_offset, &end_offset);
|
||||
size = end_offset + 1 - start_offset;
|
||||
|
||||
if (rdev_chain(target_rdev, &cse_region_rdev, start_offset, size))
|
||||
return false;
|
||||
|
||||
printk(BIOS_DEBUG, "cse_lite: CSE RW partition: offset = 0x%x, size = 0x%x\n",
|
||||
(uint32_t)start_offset, (uint32_t) size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_get_cbfs_rw_version(const struct region_device *source_rdev,
|
||||
void *cse_cbfs_rw_ver)
|
||||
{
|
||||
|
||||
if (rdev_readat(source_rdev, (void *) cse_cbfs_rw_ver, 0, sizeof(struct fw_version))
|
||||
!= sizeof(struct fw_version)) {
|
||||
printk(BIOS_ERR, "cse_lite: Failed to read CSE CBFW RW version\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_is_rw_info_valid(struct cse_bp_info *cse_bp_info)
|
||||
/*
|
||||
* Compare versions of CSE CBFS RW and CSE RW partition
|
||||
* If ver_cmp_status = 0, no update is required
|
||||
* If ver_cmp_status < 0, coreboot downgrades CSE RW region
|
||||
* If ver_cmp_status > 0, coreboot upgrades CSE RW region
|
||||
*/
|
||||
static int cse_check_version_mismatch(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev)
|
||||
{
|
||||
return cse_is_rw_status_valid(cse_bp_info);
|
||||
struct fw_version cse_cbfs_rw_ver;
|
||||
const struct fw_version *cse_rw_ver;
|
||||
|
||||
if (!cse_get_cbfs_rw_version(source_rdev, &cse_cbfs_rw_ver))
|
||||
return false;
|
||||
|
||||
printk(BIOS_DEBUG, "cse_lite: CSE CBFS RW version : %d.%d.%d.%d\n",
|
||||
cse_cbfs_rw_ver.major,
|
||||
cse_cbfs_rw_ver.minor,
|
||||
cse_cbfs_rw_ver.hotfix,
|
||||
cse_cbfs_rw_ver.build);
|
||||
|
||||
cse_rw_ver = cse_get_rw_version(cse_bp_info);
|
||||
|
||||
if (cse_cbfs_rw_ver.major != cse_rw_ver->major)
|
||||
return cse_cbfs_rw_ver.major - cse_rw_ver->major;
|
||||
else if (cse_cbfs_rw_ver.minor != cse_rw_ver->minor)
|
||||
return cse_cbfs_rw_ver.minor - cse_rw_ver->minor;
|
||||
else if (cse_cbfs_rw_ver.hotfix != cse_rw_ver->hotfix)
|
||||
return cse_cbfs_rw_ver.hotfix - cse_rw_ver->hotfix;
|
||||
else
|
||||
return cse_cbfs_rw_ver.build - cse_rw_ver->build;
|
||||
}
|
||||
|
||||
static bool cse_erase_rw_region(const struct region_device *target_rdev)
|
||||
{
|
||||
|
||||
if (rdev_eraseat(target_rdev, 0, region_device_sz(target_rdev)) < 0) {
|
||||
printk(BIOS_ERR, "cse_lite: CSE RW partition could not be erased\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_copy_rw(const struct region_device *target_rdev, const void *buf, size_t offset,
|
||||
size_t size)
|
||||
{
|
||||
if (rdev_writeat(target_rdev, buf, offset, size) < 0) {
|
||||
printk(BIOS_ERR, "cse_lite: Failed to update CSE firmware\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_is_rw_version_latest(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev)
|
||||
{
|
||||
return !cse_check_version_mismatch(cse_bp_info, source_rdev);
|
||||
}
|
||||
|
||||
static bool cse_is_update_required(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev, struct region_device *target_rdev)
|
||||
{
|
||||
return (!cse_is_rw_bp_sign_valid(target_rdev) ||
|
||||
!cse_is_rw_version_latest(cse_bp_info, source_rdev));
|
||||
}
|
||||
|
||||
static bool cse_write_rw_region(const struct region_device *target_rdev,
|
||||
const struct region_device *source_rdev)
|
||||
{
|
||||
void *cse_cbfs_rw = rdev_mmap(source_rdev, CSE_RW_VERSION_SZ,
|
||||
region_device_sz(source_rdev) - CSE_RW_VERSION_SZ);
|
||||
|
||||
/* Points to CSE CBFS RW image after boot partition signature */
|
||||
uint8_t *cse_cbfs_rw_wo_sign = (uint8_t *)cse_cbfs_rw + CSE_RW_SIGN_SIZE;
|
||||
|
||||
/* Size of CSE CBFS RW image without boot partition signature */
|
||||
uint32_t cse_cbfs_rw_wo_sign_sz = region_device_sz(source_rdev) -
|
||||
(CSE_RW_VERSION_SZ + CSE_RW_SIGN_SIZE);
|
||||
|
||||
/* Update except CSE RW signature */
|
||||
if (!cse_copy_rw(target_rdev, cse_cbfs_rw_wo_sign, CSE_RW_SIGN_SIZE,
|
||||
cse_cbfs_rw_wo_sign_sz))
|
||||
goto exit_rw_update;
|
||||
|
||||
/* Update CSE RW signature to indicate update is complete */
|
||||
if (!cse_copy_rw(target_rdev, (void *)cse_cbfs_rw, 0, CSE_RW_SIGN_SIZE))
|
||||
goto exit_rw_update;
|
||||
|
||||
rdev_munmap(source_rdev, cse_cbfs_rw_wo_sign);
|
||||
return true;
|
||||
|
||||
exit_rw_update:
|
||||
rdev_munmap(source_rdev, cse_cbfs_rw_wo_sign);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool cse_update_rw(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev, struct region_device *target_rdev)
|
||||
{
|
||||
if (!cse_erase_rw_region(target_rdev))
|
||||
return false;
|
||||
|
||||
if (!cse_write_rw_region(target_rdev, source_rdev))
|
||||
return false;
|
||||
|
||||
printk(BIOS_INFO, "cse_lite: CSE RW Update Successful\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cse_prep_for_rw_update(const struct cse_bp_info *cse_bp_info)
|
||||
{
|
||||
/*
|
||||
* To set CSE's operation mode to HMRFPO mode:
|
||||
* 1. Ensure CSE to boot from RO(BP1)
|
||||
* 2. Send HMRFPO_ENABLE command to CSE
|
||||
*/
|
||||
if (!cse_boot_to_ro(cse_bp_info))
|
||||
return false;
|
||||
|
||||
return cse_hmrfpo_enable();
|
||||
}
|
||||
|
||||
static uint8_t cse_trigger_fw_update(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev, struct region_device *target_rdev)
|
||||
{
|
||||
if (!cse_prep_for_rw_update(cse_bp_info))
|
||||
return CSE_LITE_SKU_COMMUNICATION_ERROR;
|
||||
|
||||
if (!cse_update_rw(cse_bp_info, source_rdev, target_rdev))
|
||||
return CSE_LITE_SKU_FW_UPDATE_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t cse_fw_update(const struct cse_bp_info *cse_bp_info,
|
||||
const struct region_device *source_rdev)
|
||||
{
|
||||
struct region_device target_rdev;
|
||||
|
||||
if (!cse_get_target_rdev(cse_bp_info, &target_rdev)) {
|
||||
printk(BIOS_ERR, "cse_lite: Failed to get CSE RW Partition\n");
|
||||
return CSE_LITE_SKU_RW_ACCESS_ERROR;
|
||||
}
|
||||
|
||||
if (cse_is_update_required(cse_bp_info, source_rdev, &target_rdev)) {
|
||||
printk(BIOS_DEBUG, "cse_lite: CSE RW update is initiated\n");
|
||||
return cse_trigger_fw_update(cse_bp_info, source_rdev, &target_rdev);
|
||||
}
|
||||
|
||||
if (!cse_is_rw_bp_status_valid(cse_bp_info))
|
||||
return CSE_LITE_SKU_RW_JUMP_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cse_fw_sync(void *unused)
|
||||
|
@ -350,9 +630,13 @@ void cse_fw_sync(void *unused)
|
|||
cse_trigger_recovery(CSE_LITE_SKU_COMMUNICATION_ERROR);
|
||||
}
|
||||
|
||||
if (!cse_is_rw_info_valid(&cse_bp_info.bp_info)) {
|
||||
printk(BIOS_ERR, "cse_lite: CSE RW partition is not valid\n");
|
||||
cse_trigger_recovery(CSE_LITE_SKU_RW_JUMP_ERROR);
|
||||
/* If RW blob is present in CBFS, then trigger CSE firmware update */
|
||||
uint8_t rv;
|
||||
struct region_device source_rdev;
|
||||
if (cse_get_cbfs_rdev(&source_rdev)) {
|
||||
rv = cse_fw_update(&cse_bp_info.bp_info, &source_rdev);
|
||||
if (rv)
|
||||
cse_trigger_recovery(rv);
|
||||
}
|
||||
|
||||
if (!cse_boot_to_rw(&cse_bp_info.bp_info)) {
|
||||
|
|
Loading…
Reference in New Issue