Showing with 1,460 additions and 113 deletions.
  1. +14 −1 CHANGELOG.md
  2. +155 −16 README.md
  3. +3 −0 include/flash_access.h
  4. +1 −0 { → include}/spi/spi_flash_internal.h
  5. +23 −0 include/spi/spi_lock_menu.h
  6. +51 −0 include/spi/winbond_flash.h
  7. +184 −53 sortbootorder.c
  8. +376 −0 spi/adesto.c
  9. +1 −1 spi/eon.c
  10. +1 −1 spi/gigadevice.c
  11. +1 −1 spi/macronix.c
  12. +1 −1 spi/spansion.c
  13. +2 −1 spi/spi_flash.c
  14. +1 −1 spi/sst.c
  15. +1 −1 spi/stmicro.c
  16. +2 −36 spi/winbond.c
  17. +14 −0 utils/flash_access.c
  18. +629 −0 utils/spi_lock_menu.c
15 changes: 14 additions & 1 deletion CHANGELOG.md
Expand Up @@ -7,6 +7,17 @@ Releases 4.5.x and 4.6.x are based on mainline support submitted in
[this gerrit ref](https://review.coreboot.org/#/c/14138/).

## [Unreleased]
## [v4.6.14] - 2019-06-04
### Added
- SD 3.0 mode runtime configuration
- watchdog runtime configuration with configurable timeout
- additional SPI flash lockdown hidden menu
- basic support for Adesto chips

### Changed
- all USB bootorder options have been unified and now affect all USB ports and
headers

## [v4.6.13] - 2019-02-26
### Added
- CPU boost runtime configuration
Expand Down Expand Up @@ -157,7 +168,9 @@ initial commit based on [coreboot_140908](http://pcengines.ch/tmp/coreboot_14090
### Fixed
- used proper way to access extended SPI registers

[Unreleased]: https://github.com/pcengines/sortbootorder/compare/v4.6.12...master
[Unreleased]: https://github.com/pcengines/sortbootorder/compare/v4.6.14...master
[v4.6.14]: https://github.com/pcengines/sortbootorder/compare/v4.6.13...v4.6.14
[v4.6.13]: https://github.com/pcengines/sortbootorder/compare/v4.6.12...v4.6.13
[v4.6.12]: https://github.com/pcengines/sortbootorder/compare/v4.6.11...v4.6.12
[v4.6.11]: https://github.com/pcengines/sortbootorder/compare/v4.6.10...v4.6.11
[v4.6.10]: https://github.com/pcengines/sortbootorder/compare/v4.6.9...v4.6.10
Expand Down
171 changes: 155 additions & 16 deletions README.md
Expand Up @@ -84,6 +84,12 @@ key.
slot.
* `h EHCI0 controller` - enables/disables EHCI0 controller (used in apu3)
* `l Core Performance Boost` - enables/disables CPU boost.
* `i Watchdog` - enables/disables hardware watchdog. Each time toggled, the
prompt will pop out asking to provide a timeout value in seconds (0 to
disable). **Set reasonably high value so it will be possible to disable the**
**watchdog later. Too low value may result in a reset loop!**
* `j SD 3.0 mode` - enable SD controller in 3.0 mode to allow achieving full
speeds with UHS-I SD cards
* `w Enable BIOS write protect` - enables/disables BIOS WP functionality. For
details, see descritption in [BIOS WP option](#bios-wp-option).
* `x Exit setup without save` - exits setup menu without saving the settings
Expand All @@ -98,22 +104,30 @@ one FLASH sector.

Relevant content of this file may look like this:

```
/pci@i0cf8/usb@10/usb-*@1
/pci@i0cf8/usb@10/usb-*@2
/pci@i0cf8/usb@10/usb-*@3
/pci@i0cf8/usb@10/usb-*@4
/pci@i0cf8/*@14,7
/pci@i0cf8/*@11/drive@0/disk@0
/pci@i0cf8/*@11/drive@1/disk@0
/pci@i0cf8/pci-bridge@2,5/*@0/drive@0/disk@0
/pci@i0cf8/pci-bridge@2,5/*@0/drive@1/disk@0
/rom@genroms/pxe.rom
pxen0
scon1
usben1
...
```
```
/pci@i0cf8/usb@10/usb-*@1
/pci@i0cf8/usb@10/usb-*@2
/pci@i0cf8/usb@10/usb-*@3
/pci@i0cf8/usb@10/usb-*@4
/pci@i0cf8/usb@12/usb-*@1
/pci@i0cf8/usb@12/usb-*@2
/pci@i0cf8/usb@12/usb-*@3
/pci@i0cf8/usb@12/usb-*@4
/pci@i0cf8/usb@13/usb-*@1
/pci@i0cf8/usb@13/usb-*@2
/pci@i0cf8/usb@13/usb-*@3
/pci@i0cf8/usb@13/usb-*@4
/pci@i0cf8/*@14,7
/pci@i0cf8/*@11/drive@0/disk@0
/pci@i0cf8/*@11/drive@1/disk@0
/pci@i0cf8/pci-bridge@2,5/*@0/drive@0/disk@0
/pci@i0cf8/pci-bridge@2,5/*@0/drive@1/disk@0
/rom@genroms/pxe.rom
pxen0
scon1
usben1
...
```

Rest of this file is filled with characters to meet that 4096 bytes
requirement.
Expand Down Expand Up @@ -155,6 +169,8 @@ file is used to match device letter and description with corresponding node from
UART D - Enabled
EHCI0 controller - Disabled
Core Performance Boost - Enabled
Watchdog - Disabled
SD 3.0 mode - Disabled
Redirect console output to COM2 - Disabled
BIOS write protect - Disabled
```
Expand Down Expand Up @@ -197,6 +213,129 @@ serial: 1234567890
> q
```

### Hidden flash lockdown menu

Experimental menu containing options to write and read serial number to
security registers of the SPI flash chip. To enter press `Q` (`q + shift`)
in the main menu. Option description:

* `p` - prints all the protected ranges of SPI flash for CMP bit equal to 0,
all protected ranges have its corresponding number that is used in
other commands
* `r` - prints all the protected ranges of SPI flash for CMP bit equal to 1,
all protected ranges have its corresponding number that is used in
other commands
* `b {block_no}` - sets the desired protection range to enabled, takes the
protection range number as parameters; for correct number,
please refer to commands that print protected range statuses
* `c` - clears the block protection by setting the protected range to
000000h - 000000h
* `s` - shows the current status register protection, each protection type has
its corresponding number which is used in other commands; due to the
design limitations the WP pin state detection works only if SRP0 bit in
status register is set
* `l {lock_type}` - set the desired status register protection, takes the
protection type number as a parameter; for the correct
number please refer to the command that prints the status
register protection status
* `q` - return to main menu

#### Example

```
> p
1) Protected range 000000h – 000000h (currently enabled)
2) Protected range 7E0000h – 7FFFFFh
3) Protected range 7C0000h – 7FFFFFh
4) Protected range 780000h – 7FFFFFh
5) Protected range 700000h – 7FFFFFh
6) Protected range 600000h – 7FFFFFh
7) Protected range 400000h – 7FFFFFh
8) Protected range 000000h – 01FFFFh
9) Protected range 000000h – 03FFFFh
10) Protected range 000000h – 07FFFFh
11) Protected range 000000h – 0FFFFFh
12) Protected range 000000h – 1FFFFFh
13) Protected range 000000h – 3FFFFFh
14) Protected range 000000h – 7FFFFFh
15) Protected range 7FF000h – 7FFFFFh
16) Protected range 7FE000h – 7FFFFFh
17) Protected range 7FC000h – 7FFFFFh
18) Protected range 7F8000h – 7FFFFFh
19) Protected range 000000h – 000FFFh
20) Protected range 000000h – 001FFFh
21) Protected range 000000h – 003FFFh
22) Protected range 000000h – 007FFFh
...
> s
SRP0=0 , SRP1=0, WP=?
1) Status register is in Software Protected mode. WP pin may be active.
2) Status register is NOT in Hardware Protected mode
3) Status register is NOT in Hardware Unprotected mode
4) Status register is NOT in Power Supply Lock-Down mode
5) Status register is NOT in One Time Program mode
...
> b 5
Setting block protection success!
> p
1) Protected range 000000h – 000000h
2) Protected range 7E0000h – 7FFFFFh
3) Protected range 7C0000h – 7FFFFFh
4) Protected range 780000h – 7FFFFFh
5) Protected range 700000h – 7FFFFFh (currently enabled)
6) Protected range 600000h – 7FFFFFh
7) Protected range 400000h – 7FFFFFh
8) Protected range 000000h – 01FFFFh
9) Protected range 000000h – 03FFFFh
10) Protected range 000000h – 07FFFFh
11) Protected range 000000h – 0FFFFFh
12) Protected range 000000h – 1FFFFFh
13) Protected range 000000h – 3FFFFFh
14) Protected range 000000h – 7FFFFFh
15) Protected range 7FF000h – 7FFFFFh
16) Protected range 7FE000h – 7FFFFFh
17) Protected range 7FC000h – 7FFFFFh
18) Protected range 7F8000h – 7FFFFFh
19) Protected range 000000h – 000FFFh
20) Protected range 000000h – 001FFFh
21) Protected range 000000h – 003FFFh
22) Protected range 000000h – 007FFFh
...
> l 4
Setting status register protection success!
> s
SRP0=0 , SRP1=1, WP=?
1) Status register is NOT in Software Protected mode.
2) Status register is NOT in Hardware Protected mode
3) Status register is NOT in Hardware Unprotected mode
4) Status register is in Power Supply Lock-Down mode
5) Status register is NOT in One Time Program mode
```

> For more verbose details about the protection modes and protection mechanisms
> please refer to Winbond W25Q64FV datasheet. W25Q64FV is currently the only
> supported chip by the hidden flash lockdown menu.

Be aware of the One Time Program mode. it will permanently lock the status
register. If You have left some block/range protection in place when locking,
You will not be able to erase/program that part of SPI flash. That means
**Your BIOS won't be upgraded anymore unless You solder a new unlocked chip.**
Handle with care. But, if You choose to set the permanent lock, You will be additionally
prompted for confirmation:

```
> l 5
WARNING: You are going to permanently lock status register
Are You sure? (y/n) n
Aborting...
```

## Building

### Manual build
Expand Down
3 changes: 3 additions & 0 deletions include/flash_access.h
Expand Up @@ -34,6 +34,9 @@ int read_sec(u8 reg, u8 addr, void *buf, size_t len);
int erase_sec(u8 reg, u8 addr, size_t len);
int prog_sec(u8 reg, u8 addr, const void *buf, size_t len);
int lock_sec(u8 reg);
int send_flash_cmd(u8 cmd, void *response, size_t len);
int send_flash_cmd_write(u8 command, size_t cmd_len, const void *data,
size_t data_len);
void save_flash(int flash_address, char buffer[MAX_DEVICES][MAX_LENGTH], u8 max_lines, u8 spi_wp_toggle);

#endif
Expand Up @@ -86,6 +86,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,

/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode);
Expand Down
23 changes: 23 additions & 0 deletions include/spi/spi_lock_menu.h
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2019 PC Engines GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef SPI_LOCK_MENU_H
#define SPI_LOCK_MENU_H

void handle_spi_lock_menu(void);

#endif
51 changes: 51 additions & 0 deletions include/spi/winbond_flash.h
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2019 PC Engines GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

/* M25Pxx-specific commands */
#define CMD_W25_WREN 0x06 /* Write Enable */
#define CMD_W25_WRDI 0x04 /* Write Disable */
#define CMD_W25_RDSR1 0x05 /* Read 1st Status Register */
#define CMD_W25_RDSR2 0x35 /* Read 2nd Status Register */
#define CMD_W25_WRSR 0x01 /* Write Status Register */
#define CMD_W25_READ 0x03 /* Read Data Bytes */
#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
#define CMD_W25_PP 0x02 /* Page Program */
#define CMD_W25_SE 0x20 /* Sector (4K) Erase */
#define CMD_W25_BE 0xd8 /* Block (64K) Erase */
#define CMD_W25_CE 0xc7 /* Chip Erase */
#define CMD_W25_DP 0xb9 /* Deep Power-down */
#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */
#define CMD_W25_ER_SEC 0x44 /* Erase security registers */
#define CMD_W25_WR_SEC 0x42 /* Write security registers */
#define CMD_W25_RD_SEC 0x48 /* Read security registers */

#define REG_W25_BP0 (1 << 2)
#define REG_W25_BP1 (1 << 3)
#define REG_W25_BP2 (1 << 4)
#define REG_W25_TB (1 << 5)
#define REG_W25_SEC (1 << 6)
#define REG_W25_SRP0 (1 << 7)
#define REG_W25_SRP1 (1 << 0)
#define REG_W25_CMP (1 << 6)
#define REG_W25_WPS (1 << 2)
#define REG_W25_LB1 (1 << 3)
#define REG_W25_LB2 (1 << 4)
#define REG_W25_LB3 (1 << 5)

#define ADDR_W25_SEC1 0x10
#define ADDR_W25_SEC2 0x20
#define ADDR_W25_SEC3 0x30