Showing with 84 additions and 58 deletions.
  1. +11 −1 CHANGELOG.md
  2. +7 −5 README.md
  3. +29 −6 sortbootorder.c
  4. +10 −5 spi/macronix.c
  5. +27 −41 spi/winbond.c
12 changes: 11 additions & 1 deletion CHANGELOG.md
Expand Up @@ -7,6 +7,15 @@ 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.12] - 2018-12-03
### Fixed
- BIOS WP feature for different SPI parts

### Changed
- BIOS write protection is applied after saving other changes

### Added
- COM2 redirection runtime configuration

## [v4.6.11] - 2018-09-28
### Fixed
Expand Down Expand Up @@ -144,7 +153,8 @@ 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.11...master
[Unreleased]: https://github.com/pcengines/sortbootorder/compare/v4.6.12...master
[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
[v4.6.9]: https://github.com/pcengines/sortbootorder/compare/v4.6.8...v4.6.9
Expand Down
12 changes: 7 additions & 5 deletions README.md
Expand Up @@ -44,6 +44,7 @@ saves boot order in flash.
n Network/PXE boot - Currently Disabled
u USB boot - Currently Enabled
t Serial console - Currently Enabled
k Redirect console output to COM2 - Currently Disabled
o UART C - Currently Enabled
p UART D - Currently Enabled
m Force mPCIe2 slot CLK (GPP3 PCIe) - Currently Disabled
Expand All @@ -63,13 +64,14 @@ key.
* `r Restore boot order defaults` - restores boot order to default settings
* `n Network/PXE boot` - enables/disables the network boot (iPXE)
* `u USB boot` - enables/disables boot from USB drives
* `l Legacy console redirection` - enables/disables serial redirection to the
sgabios (serial text console emulation).
* `k Redirect console output to COM2` - enables/disables serial redirection to
the COM2 port. Leaves COM1 entirely unused (except Memtest86+ still printing
on COM1) for user needs.
* `t Serial console` - enables/disables output to the serial console
Useful for legacy software, which is not using native serial port output, but
uses standard PC text console instead (eg. FreeDOS).
uses standard PC text console instead (eg. FreeDOS).
* `o UART C` - enables/disables UART C on GPIO header. Disabled UART means
enabled GPIO.
enabled GPIO.
* `p UART D` - enables/disables UART D on GPIO header. Disabled UART means
enabled GPIO.
* `m Force mPCIe2 slot CLK (GPP3 PCIe)` - enabling this option forces GPP3 PCIe
Expand All @@ -80,7 +82,7 @@ key.
slot.
* `h EHCI0 controller` - enables/disables EHCI0 controller (used in apu3)
* `w Enable BIOS write protect` - enables/disables BIOS WP functionality. For
details, see descritption in [BIOS WP option](#bios-wp-option).
details, see descritption in [BIOS WP option](#bios-wp-option).
* `x Exit setup without save` - exits setup menu without saving the settings
* `s Save configuration and exit` - exits setup menu saving the settings

Expand Down
35 changes: 29 additions & 6 deletions sortbootorder.c
Expand Up @@ -58,9 +58,14 @@ static int flash_address;

static u8 ipxe_toggle;
static u8 usb_toggle;

static u8 spi_wp_toggle;

static u8 console_toggle;
static u8 com2_toggle;

// apu5 does not have COM2
static u8 com2_available;

#ifndef TARGET_APU1
static u8 ehci0_toggle;
Expand Down Expand Up @@ -161,6 +166,15 @@ int main(void) {
token += strlen("scon");
console_toggle = token ? strtoul(token, NULL, 10) : 1;

token = strstr(bootorder_data, "com2en");
if (token == NULL)
com2_available = 0;
else {
com2_available = 1;
token += strlen("com2en");
com2_toggle = token ? strtoul(token, NULL, 10) : 1;
}

#ifndef TARGET_APU1
token = strstr(bootorder_data, "ehcien");
token += strlen("ehcien");
Expand Down Expand Up @@ -208,12 +222,12 @@ int main(void) {
break;
case 'w':
case 'W':
if (spi_wp_toggle) {
unlock_flash();
} else {
lock_flash();
}
spi_wp_toggle = is_flash_locked();
spi_wp_toggle ^= 0x1;
break;
case 'k':
case 'K':
if (com2_available)
com2_toggle ^= 0x1;
break;
case 't':
case 'T':
Expand Down Expand Up @@ -245,6 +259,8 @@ int main(void) {
update_tag_value(bootlist, &max_lines, "pxen", ipxe_toggle + '0');
update_tag_value(bootlist, &max_lines, "usben", usb_toggle + '0');
update_tag_value(bootlist, &max_lines, "scon", console_toggle + '0');
if (com2_available)
update_tag_value(bootlist, &max_lines, "com2en", com2_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartc", uartc_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartd", uartd_toggle + '0');
#ifndef TARGET_APU1
Expand Down Expand Up @@ -344,6 +360,8 @@ static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line
printf(" n Network/PXE boot - Currently %s\n", (ipxe_toggle) ? "Enabled" : "Disabled");
printf(" u USB boot - Currently %s\n", (usb_toggle) ? "Enabled" : "Disabled");
printf(" t Serial console - Currently %s\n", (console_toggle) ? "Enabled" : "Disabled");
if (com2_available)
printf(" k Redirect console output to COM2 - Currently %s\n", (com2_toggle) ? "Enabled" : "Disabled");
printf(" o UART C - Currently %s\n", (uartc_toggle) ? "Enabled" : "Disabled");
printf(" p UART D - Currently %s\n", (uartd_toggle) ? "Enabled" : "Disabled");
#ifndef TARGET_APU1
Expand Down Expand Up @@ -488,6 +506,11 @@ static void refresh_tag_values(u8 max_lines)
token += strlen("scon");
console_toggle = strtoul(token, NULL, 10);
}
token = strstr(&(bootlist_def[i][0]), "com2en");
if(token && com2_available) {
token += strlen("com2en");
com2_toggle = strtoul(token, NULL, 10);
}
#ifndef TARGET_APU1
token = strstr(&(bootlist_def[i][0]), "ehcien");
if(token) {
Expand Down
15 changes: 10 additions & 5 deletions spi/macronix.c
Expand Up @@ -213,9 +213,12 @@ static int macronix_set_lock_flags(struct spi_flash *flash, int lock)
}

if (lock) {
status |= MACRONIX_SR_BP3 | MACRONIX_SR_BP2 | MACRONIX_SR_BP1 | MACRONIX_SR_BP0;
status |= MACRONIX_SR_SRWD | MACRONIX_SR_BP3 | MACRONIX_SR_BP2 |
MACRONIX_SR_BP1 | MACRONIX_SR_BP0;
} else {
status &= ~(MACRONIX_SR_BP3 | MACRONIX_SR_BP2 | MACRONIX_SR_BP1 | MACRONIX_SR_BP0);
status &= ~(MACRONIX_SR_SRWD | MACRONIX_SR_BP3 |
MACRONIX_SR_BP2 | MACRONIX_SR_BP1 |
MACRONIX_SR_BP0);
}


Expand Down Expand Up @@ -263,8 +266,10 @@ static int macronix_is_locked(struct spi_flash *flash)

spi_flash_cmd(flash->spi, CMD_MX25XX_RDSR, &status, 1);

if ((status & (MACRONIX_SR_BP3 | MACRONIX_SR_BP2 | MACRONIX_SR_BP1 | MACRONIX_SR_BP0))
== (MACRONIX_SR_BP3 | MACRONIX_SR_BP2 | MACRONIX_SR_BP1 | MACRONIX_SR_BP0)) {
if ((status & (MACRONIX_SR_SRWD | MACRONIX_SR_BP3 | MACRONIX_SR_BP2 |
MACRONIX_SR_BP1 | MACRONIX_SR_BP0)) ==
(MACRONIX_SR_SRWD |MACRONIX_SR_BP3 | MACRONIX_SR_BP2 |
MACRONIX_SR_BP1 | MACRONIX_SR_BP0)) {
return 1;
}

Expand Down Expand Up @@ -330,7 +335,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx->flash.unlock = macronix_unlock;
mcx->flash.is_locked = macronix_is_locked;
/* The following are not yet implemented.
* Implement to enable BIOS WP and Security Registers support.
* Implement to enable Security Registers support.
*/
mcx->flash.sec_sts = macronix_sec_sts;
mcx->flash.sec_read = macronix_sec_read;
Expand Down
68 changes: 27 additions & 41 deletions spi/winbond.c
Expand Up @@ -18,11 +18,8 @@
#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_WRSR1 0x01 /* Write 1st Status Register */
#define CMD_W25_RDSR2 0x35 /* Read 2nd Status Register */
#define CMD_W25_WRSR2 0x31 /* Write 2nd Status Register */
#define CMD_W25_RDSR3 0x15 /* Read 3rd Status Register */
#define CMD_W25_WRSR3 0x11 /* Write 3rd 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 */
Expand Down Expand Up @@ -205,7 +202,7 @@ static int winbond_set_lock_flags(struct spi_flash *flash, int lock)
{
int ret;
u8 cmd;
u8 s1, s2, s3;
u8 status[2];

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
Expand All @@ -214,53 +211,36 @@ static int winbond_set_lock_flags(struct spi_flash *flash, int lock)
return ret;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR1, &s1, 1);
ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR1, &status[0], 1);
if (ret) {
spi_debug("SF: Unable to read Status Register 1\n");
goto out;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR2, &s2, 1);
if (ret) {
goto out;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR3, &s3, 1);
ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR2, &status[1], 1);
if (ret) {
spi_debug("SF: Unable to read Status Register 2\n");
goto out;
}

if (lock) {
s1 |= REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0;
status[0] |= REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0;
} else {
s1 &= ~(REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0);
status[0] &= ~(REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0);
}

s1 &= ~(REG_W25_SEC | REG_W25_TB);
s2 &= ~(REG_W25_SRP1 | REG_W25_CMP);
s3 &= ~(REG_W25_WPS);
status[0] &= ~(REG_W25_SEC | REG_W25_TB);
status[1] &= ~(REG_W25_SRP1 | REG_W25_CMP);

ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0);
if (ret < 0) {
spi_debug("SF: Enabling Write failed\n");
goto out;
}

cmd = CMD_W25_WRSR2;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd), &s2, sizeof(s2));
if (ret < 0) {
spi_debug("SF: Status register write failed\n");
goto out;
}

cmd = CMD_W25_WRSR3;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd), &s3, sizeof(s3));
if (ret < 0) {
spi_debug("SF: Status register write failed\n");
goto out;
}

cmd = CMD_W25_WRSR1;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd), &s1, sizeof(s1));
cmd = CMD_W25_WRSR;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd),
status, sizeof(status));
if (ret < 0) {
spi_debug("SF: Status register write failed\n");
goto out;
Expand Down Expand Up @@ -425,8 +405,8 @@ static int winbond_sec_sts(struct spi_flash *flash)
static int winbond_sec_lock(struct spi_flash *flash, u8 reg)
{
int ret;
u8 status = 0;
u8 cmd;
u8 status[2];

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
Expand All @@ -435,21 +415,27 @@ static int winbond_sec_lock(struct spi_flash *flash, u8 reg)
return ret;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR2, &status, sizeof(status));
ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR1, &status[0], 1);
if (ret) {
spi_debug("SF: Unable to read Status Register 1\n");
goto out;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR2, &status[1], 1);
if (ret) {
spi_debug("SF: problem reading the status register\n");
spi_debug("SF: Unable to read Status Register 2\n");
goto out;
}

switch (reg) {
case 1:
status |= REG_W25_LB1;
status[1] |= REG_W25_LB1;
break;
case 2:
status |= REG_W25_LB2;
status[1] |= REG_W25_LB2;
break;
case 3:
status |= REG_W25_LB3;
status[1] |= REG_W25_LB3;
break;
default:
spi_debug("SF: can't lock sec register, wrong index given\n");
Expand All @@ -462,9 +448,9 @@ static int winbond_sec_lock(struct spi_flash *flash, u8 reg)
goto out;
}

cmd = CMD_W25_WRSR2;
cmd = CMD_W25_WRSR;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd),
&status, sizeof(status));
status, sizeof(status));
if (ret) {
spi_debug("SF: Status register write failed\n");
goto out;
Expand Down