79 changes: 0 additions & 79 deletions libpayloadbin/.config

This file was deleted.

43 changes: 0 additions & 43 deletions libpayloadbin/build/libpayload-config.h

This file was deleted.

187 changes: 158 additions & 29 deletions sortbootorder.c
Expand Up @@ -19,7 +19,7 @@
#include <libpayload.h>
#include <cbfs.h>
#include <curses.h>
#include "spi.h"
#include "spi_flash.h"
#include "version.h"

/*** defines ***/
Expand All @@ -46,23 +46,39 @@
#define MPCIE1_SATA2 8
#define IPXE 9

#define RESET() outb(0x06, 0x0cf9)

/*** prototypes ***/
static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt );
static void move_boot_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line, u8 max_lines );
static void copy_list_line( char *src, char *dest );
static int fetch_file_from_cbfs( char *filename, char destination[MAX_DEVICES][MAX_LENGTH], u8 *line_count);
static int get_line_number(u8 line_start, u8 line_end, char key );
static void int_ids( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt );
static inline int init_flash(void);
static inline int is_flash_locked(void);
static inline int lock_flash(void);
static inline int unlock_flash(void);
static void save_flash(char buffer[MAX_DEVICES][MAX_LENGTH], u8 max_lines);
static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH], u8 *max_lines, const char * tag, char value);

/*** local variables ***/
static u8 ipxe_toggle;
static u8 usb_toggle;
static u8 sga_toggle;
static u8 spi_wp_toggle;

#ifdef COREBOOT_LEGACY
static u8 console_toggle;
static u8 ehci0_toggle;
static u8 uartc_toggle;
static u8 uartd_toggle;
#endif

static char bootlist_def[MAX_DEVICES][MAX_LENGTH];
static char bootlist_map[MAX_DEVICES][MAX_LENGTH];
static char id[MAX_DEVICES] = {0};
static struct spi_flash *flash_device;
static int flash_address;
static u8 device_toggle[MAX_DEVICES];

Expand All @@ -72,13 +88,7 @@ static u8 device_toggle[MAX_DEVICES];
* 1) Display a list of boot devices
* 2) Chosen device will be moved to the top and reset shuffled down
* 3) Display the new boot order
* 4) Give the option to:
* - Restore order defaults,
* - Serial console disable / enable
* - Network / IPXE disable / enable
* - USB boot disable / enable
* - SgaBios disable / enable
* - Exit with or without saving order
* 4) Enable/disable the chosen option
*/

int main(void) {
Expand All @@ -91,7 +101,9 @@ int main(void) {
u8 line_start = 0;
u8 line_number = 0;
char *token;
#ifndef COREBOOT_LEGACY
struct cbfs_handle *bootorder_handle;
#endif

// Set to enabled because enable toggle is not (yet) implemented for these devices
device_toggle[SDCARD] = 1;
Expand All @@ -107,11 +119,23 @@ int main(void) {

printf("\n### PC Engines apu2 setup %s ###\n", SORTBOOTORDER_VER);

if (init_flash()) {
printf("Can't initialize flash device!\n");
RESET();
}

// Find out where the bootorder file is in rom
#ifndef COREBOOT_LEGACY
bootorder_handle = cbfs_get_handle( CBFS_DEFAULT_MEDIA, BOOTORDER_FILE );
flash_address = bootorder_handle->media_offset + bootorder_handle->content_offset;
if ((u32)flash_address & 0xfff)
printf("Warning: The bootorder file is not 4k aligned!\n");
#else
char *tmp = cbfs_get_file_content( CBFS_DEFAULT_MEDIA, BOOTORDER_FILE, CBFS_TYPE_RAW, NULL );
flash_address = (int)tmp;
if ((u32)tmp & 0xfff)
printf("Warning: The bootorder file is not 4k aligned!\n");
#endif

// Get required files from CBFS
fetch_file_from_cbfs( BOOTORDER_FILE, bootlist, &max_lines );
Expand All @@ -131,6 +155,26 @@ int main(void) {
token += strlen("sgaen");
sga_toggle = token ? strtoul(token, NULL, 10) : 0;

#ifdef COREBOOT_LEGACY
token = cbfs_find_string("scon", BOOTORDER_FILE);
token += strlen("scon");
console_toggle = token ? strtoul(token, NULL, 10) : 1;

token = cbfs_find_string("ehcien", BOOTORDER_FILE);
token += strlen("ehcien");
ehci0_toggle = token ? strtoul(token, NULL, 10) : 1;

token = cbfs_find_string("uartc", BOOTORDER_FILE);
token += strlen("uartc");
uartc_toggle = token ? strtoul(token, NULL, 10) : 0;

token = cbfs_find_string("uartd", BOOTORDER_FILE);
token += strlen("uartd");
uartd_toggle = token ? strtoul(token, NULL, 10) : 0;
#endif

spi_wp_toggle = is_flash_locked();

show_boot_device_list( bootlist, max_lines, bootlist_def_ln );
int_ids( bootlist, max_lines, bootlist_def_ln );

Expand All @@ -157,17 +201,50 @@ int main(void) {
case 'L':
sga_toggle ^= 0x1;
break;
case 'w':
case 'W':
if (spi_wp_toggle) {
unlock_flash();
} else {
lock_flash();
}
spi_wp_toggle = is_flash_locked();
break;
#ifdef COREBOOT_LEGACY
case 't':
case 'T':
console_toggle ^= 0x1;
break;
case 'o':
case 'O':
uartc_toggle ^= 0x1;
break;
case 'p':
case 'P':
uartd_toggle ^= 0x1;
break;
case 'h':
case 'H':
ehci0_toggle ^= 0x1;
break;
#endif
case 's':
case 'S':
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, "sgaen", sga_toggle + '0');
#ifdef COREBOOT_LEGACY
update_tag_value(bootlist, &max_lines, "scon", console_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartc", uartc_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartd", uartd_toggle + '0');
update_tag_value(bootlist, &max_lines, "ehcien", ehci0_toggle + '0');
#endif
save_flash( bootlist, max_lines );
// fall through to exit ...
case 'x':
case 'X':
printf("\nExiting ...");
outb(0x06, 0x0cf9); /* reset */
RESET();
break;
default:
if (key >= 'a' && key <= 'j' ) {
Expand Down Expand Up @@ -251,8 +328,15 @@ static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line
printf("\n\n");
printf(" r Restore boot order defaults\n");
printf(" n Network/PXE boot - Currently %s\n", (ipxe_toggle) ? "Enabled" : "Disabled");
printf(" l Serial console redirection - Currently %s\n", (sga_toggle) ? "Enabled" : "Disabled");
printf(" u USB boot - Currently %s\n", (usb_toggle) ? "Enabled" : "Disabled");
printf(" l Legacy console redirection - Currently %s\n", (sga_toggle) ? "Enabled" : "Disabled");
#ifdef COREBOOT_LEGACY
printf(" t Serial console - Currently %s\n", (console_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");
printf(" h EHCI0 controller - Currently %s\n", (ehci0_toggle) ? "Enabled" : "Disabled");
#endif
printf(" w Enable BIOS write protect - Currently %s\n", (spi_wp_toggle) ? "Enabled" : "Disabled");
printf(" x Exit setup without save\n");
printf(" s Save configuration and exit\n");
}
Expand Down Expand Up @@ -337,13 +421,41 @@ static void move_boot_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line, u8 ma
id[0] = ln;
}

/*******************************************************************************/
static inline int init_flash(void)
{
flash_device = spi_flash_probe(0, 0, 0, 0);

if (!flash_device)
return -1;

return 0;
}

/*******************************************************************************/
static inline int is_flash_locked(void)
{
return spi_flash_is_locked(flash_device);
}

/*******************************************************************************/
static inline int lock_flash(void)
{
return spi_flash_lock(flash_device);
}

/*******************************************************************************/
static inline int unlock_flash(void)
{
return spi_flash_unlock(flash_device);
}

/*******************************************************************************/
static void save_flash(char buffer[MAX_DEVICES][MAX_LENGTH], u8 max_lines) {
int i = 0;
int k = 0;
int j, ret;
char cbfs_formatted_list[MAX_DEVICES * MAX_LENGTH];
struct spi_flash *flash;
u32 nvram_pos;

// compact the table into the expected packed list
Expand All @@ -356,28 +468,45 @@ static void save_flash(char buffer[MAX_DEVICES][MAX_LENGTH], u8 max_lines) {
k++;
}
}

cbfs_formatted_list[i++] = NUL;
spi_init();
flash = spi_flash_probe(0, 0, 0, 0);

if (!flash)
printf("Could not find SPI device\n");
else {
printf("Erasing Flash size 0x%x @ 0x%x\n", FLASH_SIZE_CHUNK, flash_address);
ret = flash->spi_erase(flash, flash_address, FLASH_SIZE_CHUNK);
if (ret) {
printf("Erase failed, ret: %d\n", ret);

// try to unlock the flash if it is locked
if (spi_flash_is_locked(flash_device)) {
spi_flash_unlock(flash_device);
if (spi_flash_is_locked(flash_device)) {
printf("Flash is write protected. Exiting...\n");
return;
}
flash->spi->rw = SPI_WRITE_FLAG;
printf("Writing %d bytes @ 0x%x\n", i, flash_address);
/* write first 512 bytes */
for (nvram_pos = 0; nvram_pos < (i & 0x1FC); nvram_pos += 4) {
flash->write(flash, nvram_pos + flash_address, sizeof(u32), (u32 *)(cbfs_formatted_list + nvram_pos));
}

printf("Erasing Flash size 0x%x @ 0x%x\n", FLASH_SIZE_CHUNK, flash_address);
ret = spi_flash_erase(flash_device, flash_address, FLASH_SIZE_CHUNK);
if (ret) {
printf("Erase failed, ret: %d\n", ret);
}

printf("Writing %d bytes @ 0x%x\n", i, flash_address);
// write first 512 bytes
for (nvram_pos = 0; nvram_pos < (i & 0xFFFC); nvram_pos += 4) {
ret = spi_flash_write(flash_device, nvram_pos + flash_address, sizeof(u32), (u32 *)(cbfs_formatted_list + nvram_pos));
if (ret) {
printf("Write failed, ret: %d\n", ret);
}
/* write remaining filler characters in one run */
flash->write(flash, nvram_pos + flash_address, sizeof(i % 4), (u32 *)(cbfs_formatted_list + nvram_pos));
}
// write remaining filler characters in one run
ret = spi_flash_write(flash_device, nvram_pos + flash_address, sizeof(i % 4), (u32 *)(cbfs_formatted_list + nvram_pos));
if (ret) {
printf("Write failed, ret: %d\n", ret);
}

if (spi_wp_toggle) {
printf("Enabling flash write protect...\n");
spi_flash_lock(flash_device);
}

spi_wp_toggle = spi_flash_is_locked(flash_device);

printf("Done\n");
}

/*******************************************************************************/
Expand Down
Empty file modified spansion.c 100755 → 100644
Empty file.
4 changes: 3 additions & 1 deletion spi.h
Expand Up @@ -61,6 +61,9 @@ struct spi_flash {
int (*write)(struct spi_flash *flash, u32 offset, size_t len,
const void *buf);
int (*spi_erase)(struct spi_flash *flash, u32 offset, size_t len);
int (*lock)(struct spi_flash *flash);
int (*unlock)(struct spi_flash *flash);
int (*is_locked)(struct spi_flash *flash);
};

struct spi_slave {
Expand All @@ -70,7 +73,6 @@ struct spi_slave {
};

void spi_init(void);
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,unsigned int max_hz, unsigned int spi_mode);

/*-----------------------------------------------------------------------
* Set up communications parameters for a SPI slave.
Expand Down
2 changes: 2 additions & 0 deletions spi_flash.c
Expand Up @@ -237,6 +237,8 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
int ret, i, shift;
u8 idcode[IDCODE_LEN], *idp;

spi_init();

spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
if (!spi) {
spi_debug("SF: Failed to set up slave\n");
Expand Down
18 changes: 18 additions & 0 deletions spi_flash.h 100755 → 100644
Expand Up @@ -46,6 +46,9 @@
#define CONTROLLER_PAGE_LIMIT ((int)(~0U>>1))
#endif

struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode);

static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf)
{
return flash->read(flash, offset, len, buf);
Expand All @@ -63,4 +66,19 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
return flash->spi_erase(flash, offset, len);
}

static inline int spi_flash_lock(struct spi_flash *flash)
{
return flash->lock(flash);
}

static inline int spi_flash_unlock(struct spi_flash *flash)
{
return flash->unlock(flash);
}

static inline int spi_flash_is_locked(struct spi_flash *flash)
{
return flash->is_locked(flash);
}

#endif /* _SPI_FLASH_H_ */
2 changes: 1 addition & 1 deletion version.h
Expand Up @@ -18,6 +18,6 @@
#ifndef _VERSION_H_
#define _VERSION_H_

#define SORTBOOTORDER_VER "v4.5.5"
#define SORTBOOTORDER_VER "v4.5.6"

#endif /* _VERSION_H_ */
115 changes: 113 additions & 2 deletions winbond.c
Expand Up @@ -17,8 +17,12 @@
/* M25Pxx-specific commands */
#define CMD_W25_WREN 0x06 /* Write Enable */
#define CMD_W25_WRDI 0x04 /* Write Disable */
#define CMD_W25_RDSR 0x05 /* Read Status Register */
#define CMD_W25_WRSR 0x01 /* Write Status Register */
#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_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 All @@ -28,6 +32,16 @@
#define CMD_W25_DP 0xb9 /* Deep Power-down */
#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */

#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)

struct winbond_spi_flash_params {
uint16_t id;
/* Log2 of page size in power-of-two mode */
Expand Down Expand Up @@ -177,6 +191,100 @@ static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len);
}

static int winbond_set_lock_flags(struct spi_flash *flash, int lock)
{
int ret;
u8 cmd;
u8 s1, s2, s3;

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
spi_debug("SF: Unable to claim SPI bus\n");
return ret;
}

ret = spi_flash_cmd(flash->spi, CMD_W25_RDSR1, &s1, 1);
if (ret) {
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);
if (ret) {
goto out;
}

if (lock) {
s1 |= 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);
}

s1 &= ~(REG_W25_SEC | REG_W25_TB);
s2 &= ~(REG_W25_SRP1 | REG_W25_CMP);
s3 &= ~(REG_W25_WPS);

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));
if (ret < 0) {
spi_debug("SF: Status register write failed\n");
goto out;
}

out:
spi_release_bus(flash->spi);
return ret;
}

static int winbond_unlock(struct spi_flash *flash)
{
return winbond_set_lock_flags(flash, 0);
}

static int winbond_lock(struct spi_flash *flash)
{
return winbond_set_lock_flags(flash, 1);
}

static int winbond_is_locked(struct spi_flash *flash)
{
u8 status = 0;

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

if ((status & (REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0))
== (REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0)) {
return 1;
}

return 0;
}

struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
{
const struct winbond_spi_flash_params *params;
Expand Down Expand Up @@ -211,6 +319,9 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)

stm->flash.write = winbond_write;
stm->flash.spi_erase = winbond_erase;
stm->flash.lock = winbond_lock;
stm->flash.unlock = winbond_unlock;
stm->flash.is_locked = winbond_is_locked;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
#else
Expand Down