9 changes: 9 additions & 0 deletions 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.0.26] - 2019-06-07
### Changed
- [updated SeaBIOS to rel-1.12.1.2](https://github.com/pcengines/seabios/blob/apu_support/CHANGELOG.md#rel-11212---2019-06-04)
- [updated sortbootorder to v4.6.14](https://github.com/pcengines/sortbootorder/blob/master/CHANGELOG.md#v4614---2019-06-04)
- SD 3.0 mode is now runtime configurable
- watchdog is now runtime configurable
- all USB devices have now a single boot order priority
- ECC presence is reported in SMBIOS tables

## [v4.0.25] - 2019-03-07
### Changed
- sortbootorder updated to v4.6.13 introducing CPU boost runtime configuration
Expand Down
2 changes: 1 addition & 1 deletion configs/pcengines_apu2.config
Expand Up @@ -414,7 +414,7 @@ CONFIG_SEABIOS_PCENGINES=y
# CONFIG_SEABIOS_STABLE is not set
# CONFIG_SEABIOS_MASTER is not set
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.0.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_ADD_SERCON_PORT_FILE=y
CONFIG_SEABIOS_SERCON_PORT_ADDR=0x3f8
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
Expand Down
2 changes: 1 addition & 1 deletion configs/pcengines_apu3.config
Expand Up @@ -414,7 +414,7 @@ CONFIG_SEABIOS_PCENGINES=y
# CONFIG_SEABIOS_STABLE is not set
# CONFIG_SEABIOS_MASTER is not set
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.0.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_ADD_SERCON_PORT_FILE=y
CONFIG_SEABIOS_SERCON_PORT_ADDR=0x3f8
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
Expand Down
2 changes: 1 addition & 1 deletion configs/pcengines_apu4.config
Expand Up @@ -414,7 +414,7 @@ CONFIG_SEABIOS_PCENGINES=y
# CONFIG_SEABIOS_STABLE is not set
# CONFIG_SEABIOS_MASTER is not set
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.0.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_ADD_SERCON_PORT_FILE=y
CONFIG_SEABIOS_SERCON_PORT_ADDR=0x3f8
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
Expand Down
2 changes: 1 addition & 1 deletion configs/pcengines_apu5.config
Expand Up @@ -414,7 +414,7 @@ CONFIG_SEABIOS_PCENGINES=y
# CONFIG_SEABIOS_STABLE is not set
# CONFIG_SEABIOS_MASTER is not set
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.0.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_ADD_SERCON_PORT_FILE=y
CONFIG_SEABIOS_SERCON_PORT_ADDR=0x3f8
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/sortbootorder/Makefile.inc
@@ -1,4 +1,4 @@
version=4.6.13
version=4.6.14
branch_name=v$(version)
project_url=https://github.com/pcengines/sortbootorder/archive/$(branch_name).tar.gz
archive_name=$(branch_name).tar.gz
Expand Down
28 changes: 28 additions & 0 deletions src/arch/x86/boot/smbios.c
Expand Up @@ -75,6 +75,10 @@ int smbios_string_table_len(char *start)
p += i;
len += i;
}

if (!len)
return 2;

return len + 1;
}

Expand Down Expand Up @@ -337,6 +341,26 @@ static int smbios_write_type11(unsigned long *current, int *handle)
return len;
}

static int smbios_write_type16(unsigned long *current, int *handle)
{
int len = fill_mainboard_smbios_type16(current, handle);
if(len){
*current += len;
(*handle)++;
}
return len;
}

static int smbios_write_type17(unsigned long *current, int *handle, int *type16_handle)
{
int len = fill_mainboard_smbios_type17(current, handle, type16_handle);
if(len){
*current += len;
(*handle)++;
}
return len;
}

static int smbios_write_type32(unsigned long *current, int handle)
{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
Expand Down Expand Up @@ -408,6 +432,7 @@ unsigned long smbios_write_tables(unsigned long current)
struct smbios_entry *se;
unsigned long tables;
int len, handle = 0;
int type16_handle = 0;

current = ALIGN(current, 16);
printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current);
Expand All @@ -426,6 +451,9 @@ unsigned long smbios_write_tables(unsigned long current)
#if CONFIG_ELOG
len += elog_smbios_write_type15(&current, handle++);
#endif
type16_handle = handle;
len += smbios_write_type16(&current, &handle);
len += smbios_write_type17(&current, &handle, &type16_handle);
len += smbios_write_type32(&current, handle++);

len += smbios_walk_device_tree(all_devices, &handle, &current);
Expand Down
110 changes: 104 additions & 6 deletions src/include/smbios.h
Expand Up @@ -8,10 +8,8 @@ int smbios_add_string(char *start, const char *str);
int smbios_string_table_len(char *start);

/* Used by mainboard to add an on-board device */
int smbios_write_type41(unsigned long *current, int *handle,
const char *name, u8 instance, u16 segment,
u8 bus, u8 device, u8 function);

int smbios_write_type41(unsigned long *current, int *handle, const char *name, u8 instance, u16 segment, u8 bus, u8 device, u8 function);

const char *smbios_mainboard_manufacturer(void);
const char *smbios_mainboard_product_name(void);

Expand All @@ -21,6 +19,8 @@ void smbios_mainboard_set_uuid(u8 *uuid);
const char *smbios_mainboard_bios_version(void);
const char *smbios_mainboard_sku(void);
u8 smbios_mainboard_enclosure_type(void);
int fill_mainboard_smbios_type16(unsigned long *current, int *handle);
int fill_mainboard_smbios_type17(unsigned long *current, int *handle, int *type16_handle);

#define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7)
#define BIOS_CHARACTERISTICS_PC_CARD (1 << 8)
Expand All @@ -35,6 +35,105 @@ u8 smbios_mainboard_enclosure_type(void);
#define BIOS_EXT1_CHARACTERISTICS_ACPI (1 << 0)
#define BIOS_EXT2_CHARACTERISTICS_TARGET (1 << 2)

typedef enum {
MEMORY_BUS_WIDTH_8 = 0,
MEMORY_BUS_WIDTH_16 = 1,
MEMORY_BUS_WIDTH_32 = 2,
MEMORY_BUS_WIDTH_64 = 3,
MEMORY_BUS_WIDTH_128 = 4,
MEMORY_BUS_WIDTH_256 = 5,
MEMORY_BUS_WIDTH_512 = 6,
MEMORY_BUS_WIDTH_1024 = 7,
MEMORY_BUS_WIDTH_MAX = 7,
} smbios_memory_bus_width;

typedef enum {
MEMORY_FORMFACTOR_OTHER = 0x01,
MEMORY_FORMFACTOR_UNKNOWN = 0x02,
MEMORY_FORMFACTOR_SIMM = 0x03,
MEMORY_FORMFACTOR_SIP = 0x04,
MEMORY_FORMFACTOR_CHIP = 0x05,
MEMORY_FORMFACTOR_DIP = 0x06,
MEMORY_FORMFACTOR_ZIP = 0x07,
MEMORY_FORMFACTOR_PROPRIETARY_CARD = 0x08,
MEMORY_FORMFACTOR_DIMM = 0x09,
MEMORY_FORMFACTOR_TSOP = 0x0a,
MEMORY_FORMFACTOR_ROC = 0x0b,
MEMORY_FORMFACTOR_RIMM = 0x0c,
MEMORY_FORMFACTOR_SODIMM = 0x0d,
MEMORY_FORMFACTOR_SRIMM = 0x0e,
MEMORY_FORMFACTOR_FBDIMM = 0x0f,
} smbios_memory_form_factor;

typedef enum {
MEMORY_TYPE_OTHER = 0x01,
MEMORY_TYPE_UNKNOWN = 0x02,
MEMORY_TYPE_DRAM = 0x03,
MEMORY_TYPE_EDRAM = 0x04,
MEMORY_TYPE_VRAM = 0x05,
MEMORY_TYPE_SRAM = 0x06,
MEMORY_TYPE_RAM = 0x07,
MEMORY_TYPE_ROM = 0x08,
MEMORY_TYPE_FLASH = 0x09,
MEMORY_TYPE_EEPROM = 0x0a,
MEMORY_TYPE_FEPROM = 0x0b,
MEMORY_TYPE_EPROM = 0x0c,
MEMORY_TYPE_CDRAM = 0x0d,
MEMORY_TYPE_3DRAM = 0x0e,
MEMORY_TYPE_SDRAM = 0x0f,
MEMORY_TYPE_SGRAM = 0x10,
MEMORY_TYPE_RDRAM = 0x11,
MEMORY_TYPE_DDR = 0x12,
MEMORY_TYPE_DDR2 = 0x13,
MEMORY_TYPE_DDR2_FBDIMM = 0x14,
MEMORY_TYPE_DDR3 = 0x18,
MEMORY_TYPE_FBD2 = 0x19,
MEMORY_TYPE_DDR4 = 0x1a,
MEMORY_TYPE_LPDDR = 0x1b,
MEMORY_TYPE_LPDDR2 = 0x1c,
MEMORY_TYPE_LPDDR3 = 0x1d,
MEMORY_TYPE_LPDDR4 = 0x1e,
MEMORY_TYPE_LOGICAL_NON_VOLATILE_DEVICE = 0x1f,
} smbios_memory_type;

typedef enum {
MEMORY_ARRAY_LOCATION_OTHER = 0x01,
MEMORY_ARRAY_LOCATION_UNKNOWN = 0x02,
MEMORY_ARRAY_LOCATION_SYSTEM_BOARD = 0x03,
MEMORY_ARRAY_LOCATION_ISA_ADD_ON = 0x04,
MEMORY_ARRAY_LOCATION_EISA_ADD_ON = 0x05,
MEMORY_ARRAY_LOCATION_PCI_ADD_ON = 0x06,
MEMORY_ARRAY_LOCATION_MCA_ADD_ON = 0x07,
MEMORY_ARRAY_LOCATION_PCMCIA_ADD_ON = 0x08,
MEMORY_ARRAY_LOCATION_PROPRIETARY_ADD_ON = 0x09,
MEMORY_ARRAY_LOCATION_NUBUS = 0x0a,
MEMORY_ARRAY_LOCATION_PC_98_C20_ADD_ON = 0xa0,
MEMORY_ARRAY_LOCATION_PC_98_C24_ADD_ON = 0xa1,
MEMORY_ARRAY_LOCATION_PC_98_E_ADD_ON = 0xa2,
MEMORY_ARRAY_LOCATION_PC_98_LOCAL_BUS_ADD_ON = 0xa3,
} smbios_memory_array_location;

typedef enum {
MEMORY_ARRAY_USE_OTHER = 0x01,
MEMORY_ARRAY_USE_UNKNOWN = 0x02,
MEMORY_ARRAY_USE_SYSTEM = 0x03,
MEMORY_ARRAY_USE_VIDEO = 0x04,
MEMORY_ARRAY_USE_FLASH = 0x05,
MEMORY_ARRAY_USE_NVRAM = 0x06,
MEMORY_ARRAY_USE_CACHE = 0x07,
} smbios_memory_array_use;

typedef enum {
MEMORY_ARRAY_ECC_OTHER = 0x01,
MEMORY_ARRAY_ECC_UNKNOWN = 0x02,
MEMORY_ARRAY_ECC_NONE = 0x03,
MEMORY_ARRAY_ECC_PARITY = 0x04,
MEMORY_ARRAY_ECC_SINGLE_BIT = 0x05,
MEMORY_ARRAY_ECC_MULTI_BIT = 0x06,
MEMORY_ARRAY_ECC_CRC = 0x07,
} smbios_memory_array_ecc;


#define SMBIOS_STATE_SAFE 3
typedef enum {
SMBIOS_BIOS_INFORMATION=0,
Expand Down Expand Up @@ -246,9 +345,8 @@ struct smbios_type17 {
u8 asset_tag;
u8 part_number;
u8 attributes;
u16 extended_size;
u32 extended_size;
u16 clock_speed;

char eos[2];
} __attribute__((packed));

Expand Down
130 changes: 130 additions & 0 deletions src/mainboard/pcengines/apu2/bios_knobs.c
Expand Up @@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <string.h>
#include <console/console.h>
#include <cbfs_core.h>
#include "bios_knobs.h"
Expand Down Expand Up @@ -236,3 +237,132 @@ bool check_mpcie2_clk(void)

return false;
}

bool check_sd3_mode(void)
{
u8 sd3mode;

//
// Find the SD 3.0 mode item
//
sd3mode = check_knob_value("sd3mode");

switch (sd3mode) {
case 0:
return false;
break;
case 1:
return true;
break;
default:
printk(BIOS_INFO, "Missing or invalid sd3mode knob."
" Disable SD3.0 mode.\n");
break;
}

return false;
}

static int _valid(char ch, int base)
{
char end = (base > 9) ? '9' : '0' + (base - 1);

/* all bases will be some subset of the 0-9 range */

if (ch >= '0' && ch <= end)
return 1;

/* Bases > 11 will also have to match in the a-z range */

if (base > 11) {
if (tolower(ch) >= 'a' &&
tolower(ch) <= 'a' + (base - 11))
return 1;
}

return 0;
}

/* Return the "value" of the character in the given base */

static int _offset(char ch, int base)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
else
return 10 + tolower(ch) - 'a';
}


static unsigned long long int strtoull(const char *ptr, char **endptr, int base)
{
unsigned long long int ret = 0;

if (endptr != NULL)
*endptr = (char *) ptr;

/* Purge whitespace */

for( ; *ptr && isspace(*ptr); ptr++);

if (!*ptr)
return 0;

/* Determine the base */

if (base == 0) {
if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
base = 16;
else if (ptr[0] == '0') {
base = 8;
ptr++;
}
else
base = 10;
}

/* Base 16 allows the 0x on front - so skip over it */

if (base == 16) {
if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X') &&
_valid(ptr[2], base))
ptr += 2;
}

for( ; *ptr && _valid(*ptr, base); ptr++)
ret = (ret * base) + _offset(*ptr, base);

if (endptr != NULL)
*endptr = (char *) ptr;

return ret;
}

#define ULONG_MAX ((unsigned long int)~0UL)

static unsigned long int strtoul(const char *ptr, char **endptr, int base)
{
unsigned long long val = strtoull(ptr, endptr, base);
if (val > ULONG_MAX) return ULONG_MAX;
return val;
}

u16 get_watchdog_timeout(void)
{
const char *boot_file = NULL;
size_t boot_file_len = 0;
u16 timeout;

boot_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, BOOTORDER_FILE,
CBFS_TYPE_RAW, &boot_file_len);
if (boot_file == NULL)
printk(BIOS_EMERG, "file [%s] not found in CBFS\n", BOOTORDER_FILE);
if (boot_file_len < 4096)
printk(BIOS_EMERG, "Missing bootorder data.\n");
if (boot_file == NULL || boot_file_len < 4096)
return -1;

timeout = (u16) strtoul(findstr(boot_file, "watchdog"), NULL, 16);

return timeout;
}