Flash operations in do_flash_op() involve waiting polling for the chip
to complete the operation. If a concurrent operation is started while
another operation is in progress, flash gets confused and locks up.
Let's add a mutex to ensure that flash operation runs to completion
before another operation starts.
BRANCH=cr50
BUG=b:67651754
TEST=multiple times ran firmware update while the device was coming up
and saving TPM status in NVMEM. Observed no failures.
Change-Id: I777a38f8a63cf17d60edb11cc3f916a4ea904741
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/894180
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
For the upcoming header restore vendor command implementation there is
a need to allow rw access to the alternative RO area.
A static function for this is available in upgrade_fw.c, let's make it
available to other users.
BRANCH=cr50
BUG=b:35580805
TEST=verified that it is still possible to update the RO.
Change-Id: I879804ff180c5d00cf6860ce5669f2fe48731832
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/457501
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
This command is handy in debug images when rollback protection needs
to be reset.
Manufacturing data stored in the last quarter of the INFO1 space is
preserved across the erase session.
BRANCH=cr50
BUG=b:35774863
TEST=built a non-debug image with the first map location in the
manifest set to zero, booted the new image. Then built and booted
a debug image with this patch included. Using sysinfo command
verified that the info map has one location zeroed, then ran
eraseflashinfo command and checked sysinfo output again. The info
map shows no more zeroed locations, and tpm still reports statues
as "manufacutred"
Change-Id: I58e2a6f6371b6ce656c1d6cc373dfdc6f9d9f5be
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/450906
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
The cr50 RO image compares INFO rollback map space against the
contents of the RW image's infomap field.
To ensure that no rollback is possible, the RW should verify that the
INFO space state is consistent with the current RW and RW_B headers,
and if not, update the INFO state to comply.
This should happen only when running prod images, so that debug images
could be rolled back if so desired.
Also fixed the bug in functions enabling read and write access to the
INFO1 region. Write access is now a superset of read access setting.
BRANCH=cr50
BUG=b:35774863
TEST=as follows:
- built and ran a new image, observed it start successfully;
- modified the manifest to erase the first map location, built and
ran a new image, observed it start successfully
- restored the manifest, built and tried running a new image,
observed that the earlier version is starting.
Change-Id: I62253c3e98cd24ed24424b8bb9de22692a262d89
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/447966
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Flash INFO access API presently is hardcoded to access the endorsement
space. To enable INFO map based rollback protection one needs to be
able to access different areas of the INFO.
The FLASH REGION3 register used by the API is in fact used for NVMEM
flash accesses too, so it is better to leave it alone and use REGION6
for the purpose of accessing of the INFO space.
The API now requires the user to specify flash offset and region size,
the size must be power of 2, the offset must be aligned at size, and
the region must not spill beyond the INFO space address range.
BRANCH=cr50
BUG=b:35774863
TEST=with the rest of the patches applied it is possible to erase the
base word in the info map segment;
reading of the endorsement space at startup still works fine.
Change-Id: I008165ee9e11a7b49985d2b30683509cf6699431
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/447965
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
In preparation for adding the rollback protection block, pass
EC_FLASH_PROTECT_RO/ALL_AT_BOOT to flash_[physical_]protect_at_boot,
instead of an enumeration no protection/RO/ALL.
This will later allow us to protect/unprotect the rollback region only,
by adding a EC_FLASH_PROTECT_ROLLBACK_AT_BOOT flag.
BRANCH=none
BUG=chrome-os-partner:61671
TEST=Build hammer with CONFIG_CMD_FLASH command, so that write protection
can be checked with flasherase/flashwrite.
TEST=On hammer (stm32f072):
flashinfo => RO+RW not protected
flashwp true; reboot => only RO protected
flashwp rw; reboot => RO+RW protected
flashwp norw; reboot => only RO protected
TEST=On reef (npcx):
deassert WP, flashwp false; flashinfo => RO+RW not protected
flashwp true => only RO protected
reboot => only RO protected
flashwp rw => RO+RW protected
reboot => only RO protected
Change-Id: Iec96a7377baabc9100fc59de0a31505095a3499f
Reviewed-on: https://chromium-review.googlesource.com/430518
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This fixes a build failure using gcc 5.3 where opcode and max_attempts
are used before being initialized.
BUG=None
BRANCH=None
TEST=Build all boards successfully.
Change-Id: Ia7c4273f8812cca9f127fcd71101ce3a4e4ad4c7
Signed-off-by: Martin Roth <martinroth@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/370662
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Reviewed-by: Nagendra Modadugu <ngm@google.com>
* Added MACRO for specifying row size of flash device.
* Set chip/g specific values for flash row size.
The flash API for g/chip will segment large write operations into a
maximum of 32 word blocks for batch writes to flash memory. Prior to
the change in this commit, the segmentation will adhere to avoiding
crossing page boundaries (2048B) but will not respect row boundaries
(256B). The flash controller will reject any write op that crosses a
row boundary and set a row boundary violation code on its error
register.
BRANCH=none
BUG=b:30819377
TEST=make BOARD=haven_dev
Change-Id: I489122ec0f0db6374dd373a1385c3012bdface20
Reviewed-on: https://chromium-review.googlesource.com/371003
Commit-Ready: Bill Richardson <wfrichar@chromium.org>
Commit-Ready: Johnnie Chan <johnniec@google.com>
Tested-by: Johnnie Chan <johnniec@google.com>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
This change implements logic for installing
endorsement certificates in the RW section.
The endorsement certificates are initially
provisioned in a fixed RO flash region and
are copied in the RW TPM data region (once
this region has been initialized).
Also add code for reading from the info bank,
which is where the endorsement seed is
initially stored.
BRANCH=none
BUG=chrome-os-partner:43025,chrome-os-partner:47524
BUG=chrome-os-partner:50115
TEST=TCG tests running
Change-Id: Id8c16d399202eee4ac0c4e397bdd29641ff9d2f3
Signed-off-by: nagendra modadugu <ngm@google.com>
Reviewed-on: https://chromium-review.googlesource.com/362402
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
We had been putting the NVMEM flash where the boot rom would
expect to find RO_B, preventing us from ever being able to update
the bootloader.
With this CL, we're rearranging the flash to support both RO_A
and RO_B. The current flash layout now looks like this:
0x40000 RO_A
0x44000 RW_A
0x7c000 TOP_A
0x80000 RO_B
0x84000 RW_B
0xbc000 NVMEM
0xbffff <end of flash>
BUG=chrome-os-partner:44803
BRANCH=none
TEST=make buildall, also manual tests on Cr50 boards
First, check that our current process still works:
make BOARD=cr50 CR50_RO_KEY=cr50_rom0-dev-blsign.pem.pub
spiflash -i -v build/cr50/ec.hex
Yep, it does, but that only produces RO_A, not RO_B.
To test the dual RO behavior, I used prebuilt RO_A and RO_B blobs
for the bootloaders, signed using Marius' new scheme.
Build the unsigned image, then sign it using Vadim's scripts:
make BOARD=cr50 -j30
~/bin/bs hex
We'll garble various bits of the full image to invalidate each of
the four RO/RW/A/B parts.
Find lines common to both ROs and common to both RWs:
sort B1*.hex | uniq -c | grep ' 2 ' | \
awk '{print $2}' | sort > tmp.ro2
sort build/cr50/RW/ec.RW*.signed.hex | uniq -c | grep ' 2 ' | \
awk '{print $2}' | sort > tmp.rw2
ro=$(diff tmp.ro2 tmp.rw2 | grep '<' | head -1 | awk '{print $2}')
rw=$(diff tmp.ro2 tmp.rw2 | grep '>' | head -1 | awk '{print $2}')
Double-check to be sure we don't have any false matches:
grep -l $ro build/cr50/RW/ec.RW*.signed.hex B1_*.hex
grep -l $rw build/cr50/RW/ec.RW*.signed.hex B1_*.hex
The pre-signed RO_A image is older than RO_B, but both have the
same epoch/major/minor, which is all that the bootrom checks for.
It doesn't look at the timestamp.
The RW_A is older than RW_B because of the sequential signing
process. The RO bootloaders will check their timestamp, so RW_B
should be preferred.
RO_A RO_B RW_A RW_B
good good good good
cat build/cr50/RW/ec.RW*.signed.hex B1_*.hex > foo.hex
spiflash -v -i foo.hex
jump @00040400
jump @00084000
=> boots RO_A -> RW_B
RO_A RO_B RW_A RW_B
good good good bad
cat build/cr50/RW/ec.RW*.signed.hex B1_*.hex > foo.hex
ln=$(grep -n $rw foo.hex | awk -F: 'NR==2 {print $1}')
sed -i "${ln}d" foo.hex
spiflash -v -i foo.hex
jump @00040400
jump @00044000
=> boots RO_A -> RW_A
RO_A RO_B RW_A RW_B
bad good good good
cat build/cr50/RW/ec.RW*.signed.hex B1_*.hex > foo.hex
ln=$(grep -n $ro foo.hex | awk -F: 'NR==1 {print $1}')
sed -i "${ln}d" foo.hex
spiflash -v -i foo.hex
jump @00080400
jump @00084000
=> boots RO_B -> RW_B
RO_A RO_B RW_A RW_B
bad good good bad
cat build/cr50/RW/ec.RW*.signed.hex B1_*.hex > foo.hex
ln=$(grep -n $ro foo.hex | awk -F: 'NR==1 {print $1}')
sed -i "${ln}d" foo.hex
ln=$(grep -n $rw foo.hex | awk -F: 'NR==2 {print $1}')
sed -i "${ln}d" foo.hex
spiflash -v -i foo.hex
jump @00080400
jump @00044000
=> boots RO_B -> RW_A
Yay.
Now make sure RW_A and RW_B can be updated using usb_updater.
\rm -rf build
make BOARD=cr50 -j30
~/bin/bs
./extra/usb_updater/usb_updater build/cr50/ec.bin
I'm running RW_A, it updates and reboots into RW_B. Good.
reboot 5 times, and it reverts to RW_A.
Power cycle and it goes to RW_B again.
Update to RW_A.
\rm -rf build
make BOARD=cr50 -j30
~/bin/bs
./extra/usb_updater/usb_updater build/cr50/ec.bin
I'm running RW_B, it updates and reboots into RW_A. Good.
reboot 5 times, and it reverts to RW_B.
Power cycle and it goes to RW_A again.
Cool.
Change-Id: I6c1689920de06c72c69f58ad2ef1059d9ee0d75f
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/362521
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
State that needs to survive re-flashing
of RO+RW is stored in the INFO bank. An
example of such state is manufacture secrets,
which need to survive reflashing from the
personalize firmware to the initial TPM2
firmware.
This change adds support for writing to
the writeable flash info bank.
BRANCH=none
BUG=chrome-os-partner:43025
TEST=manually verified info1 reads and writes
Signed-off-by: nagendra modadugu <ngm@google.com>
Change-Id: I9226e2161e036d1dacccbe55b67724b449983008
Reviewed-on: https://chromium-review.googlesource.com/351274
Commit-Ready: Nagendra Modadugu <ngm@google.com>
Tested-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Flash writes must have starting offsets and byte lengths that are
multiples of 4 bytes. This requirement is already covered. One
additional requirement is that a batch write not cross a flash
block boundary. Added a check in flash_physical_write() to check
if this boundary would be crossed and if so to reduce the write
size so that it ends at the block boundary.
BUG=chrome-os-partner:44745
BRANCH=none
TEST=manual
Used the TPM NVMem section and executed flash writes/reads using
a console command utility that I created to test NVMem accesses.
Note that the console output only exists in the console command
related functions.
This test has the offset 12 bytes from the block boundary and
64 bytes long. The counting pattern shows that the write fills the
last 12 bytes, then moves to the next block as expected.
> nvmem wr 0xff4 0x40 3
nvmem wr: o = ff4, s = 64|0x40
start = 0xff4, end = 0x1034
block 0: block_offset = 0x40800
Call Erase(0x80800, 0x800)
block 1: block_offset = 0x41000
Call Erase(0x81000, 0x800)
Nvmem: writing 64 bytes, start = 0x80ff4
> nvmem rd 0xfe0 0x80
nvmem rd: o = fe0, s = 128|0x80
0x80fe0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x80ff0: ff ff ff ff 00 01 02 03 04 05 06 07 08 09 0a 0b
0x81000: 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b
0x81010: 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b
0x81020: 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
0x81030: 3c 3d 3e 3f ff ff ff ff ff ff ff ff ff ff ff ff
Also tested the case where a write should end exactly at
the block boundary.
> nvmem wr 0xff0 16 3
nvmem wr: o = ff0, s = 16|0x10
start = 0xff0, end = 0x1000
block 0: block_offset = 0x40800
Call Erase(0x80800, 0x800)
Nvmem: writing 16 bytes, start = 0x80ff0
>
> nvmem rd 0xfe0 0x80
nvmem rd: o = fe0, s = 128|0x80
0x80fe0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x80ff0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0x81000: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
0x81010: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
Change-Id: Icbe66d3f79d84ed29ecc6207537ea0bf42781f3c
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/330175
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
The g chip is used in multiple designs, likely to have different flash
memory layout and access permissions.
This patch introduces a mechanism which allows the board layer to
provide flash configuration information to the flash driver.
The flash region which is going to be enabled for write access depends
on the area the code is executing from. If running from the bottom
half (A), the whole top half should be writeable (this includes both
NVRAM area and the B code space). If running from B, the writeable
area starts on top of RO and extends to the end of NVRAM.
CQ-DEPEND=CL:*248190
BRANCH=none
BUG=chrome-os-partner:37754
TEST=with the rest of the patches applied verified that software
update can happen in both spaces, A and B.
Change-Id: Iab1c1a2766ae9bcfe04ff170c010f180cd1f770f
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/327412
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Nadim Taha <ntaha@chromium.org>
It is difficult to tell what went wrong if a flash operation failed.
This patch adds printouts in cases of failure. The extension command
console channel is used.
BRANCH=none
BUG=chrome-os-partner:37754
TEST=observed error messages reported while debugging firmware update
code.
Change-Id: I73d509ac5088249e8d34e32e760f3d2f063c91cd
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/327411
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
The max retry counts are based on the TSMC specification. This is a necessary
change given that we're using their smart program/erase algorithms.
BRANCH=none
BUG=chrome-os-partner:45366
TEST=Tested RW updates.
Change-Id: I18ca09e54ce13f2cf75dac32fb2457d5963ca040
Signed-off-by: Nadim Taha <ntaha@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/325535
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Security settings prevent flash updates by default. This allows
erase and writes to flash bank 1 (0x80000 - 0xbffff). Note that
this doesn't allow for execution of any code you might put there.
That requires additional steps which are not part of this CL.
BUG=chrome-os-partner:44745
BRANCH=none
TEST=manual
Pick an unused section of flash and use the flasherase and
flashwrite commands to test it. The flashwrite command fills a
buffer with bytes, counting up (0x00, 0x01, 0x02, 0x03, ...),
then writes that buffer to the address given.
Note that the "md" command uses the absolute address, while the
flash commands use the offset address within the flash memory.
For example:
> md 0xbb000 16
000BB000: ffffffff ffffffff ffffffff ffffffff
000BB010: ffffffff ffffffff ffffffff ffffffff
000BB020: ffffffff ffffffff ffffffff ffffffff
000BB030: ffffffff ffffffff ffffffff ffffffff
> flasherase 0x7b000 0x800
Erasing 2048 bytes at 0x7b000...
> md 0xbb000 16
000BB000: ffffffff ffffffff ffffffff ffffffff
000BB010: ffffffff ffffffff ffffffff ffffffff
000BB020: ffffffff ffffffff ffffffff ffffffff
000BB030: ffffffff ffffffff ffffffff ffffffff
> flashwrite 0x7b000 0x800
Writing 2048 bytes to 0x7b000...
> md 0xbb000 16
000BB000: 03020100 07060504 0b0a0908 0f0e0d0c
000BB010: 13121110 17161514 1b1a1918 1f1e1d1c
000BB020: 23222120 27262524 2b2a2928 2f2e2d2c
000BB030: 33323130 37363534 3b3a3938 3f3e3d3c
> md .b 0xbb000 16
000BB000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
>
Change-Id: Ia9fb6415bcc65ab92cab8132d8cf615215804a6d
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/306687
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>