Various minor sandbox improvements

Better buildman warning handling
 Misc other things
 -----BEGIN PGP SIGNATURE-----
 
 iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAlv19KwRHHNqZ0BjaHJv
 bWl1bS5vcmcACgkQfxc6PpAIreaWtwf/Xq0DuDuTyoqfVuGJk/SyS4PzZ7Z778oz
 YxX7Do0biHMqT+3QnvhRGsYQQck2jOqP/Romr/U3q1+jDRT53/RDBnJmG4lQ/toF
 79mShpx5vm/QZKf1QI1nJv57P1xRrP8VcDaqrHKsJ5v5sAaPls5y0ik+IzfSVlJX
 mw0rs1cSKeoDKXu7a8AnP2OPJPhGT0C9Gougg5nnjyAwTs2dww8w396vyZmw0S3m
 KnAOrvxrVGx7AxQFeD1T0/Fvc4jWrR82HBcibuYLuSSxFtnt26iEWfaP9CjKeV6h
 P5/T3vxFolKesyG+2/OVeIlTvISHeXmsdYBpVtxDbHETWzxU0xDzzQ==
 =SRxW
 -----END PGP SIGNATURE-----

Merge tag 'pull-tg18' of git://git.denx.de/u-boot-dm

Various minor sandbox improvements
Better buildman warning handling
Misc other things
This commit is contained in:
Tom Rini 2018-11-23 17:25:27 -05:00
commit 5830791d91
52 changed files with 908 additions and 147 deletions

View file

@ -1048,9 +1048,11 @@ u-boot.ldr: u-boot
# binman
# ---------------------------------------------------------------------------
# Use 'make BINMAN_DEBUG=1' to enable debugging
quiet_cmd_binman = BINMAN $@
cmd_binman = $(srctree)/tools/binman/binman -d u-boot.dtb -O . \
-I . -I $(srctree)/board/$(BOARDDIR) $<
cmd_binman = $(srctree)/tools/binman/binman -u -d u-boot.dtb -O . -m \
-I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \
$(if $(BINMAN_DEBUG),-D) $(BINMAN_$(@F)) $<
OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex

View file

@ -306,7 +306,7 @@ static int setup_mac_address(void)
ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET,
otp, sizeof(otp));
if (ret)
if (ret < 0)
return ret;
for (i = 0; i < 6; i++)
@ -344,7 +344,7 @@ static int setup_serial_number(void)
ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET,
otp, sizeof(otp));
if (ret)
if (ret < 0)
return ret;
sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]);

View file

@ -2,7 +2,7 @@
/*
* Copyright (c) 2011 The Chromium OS Authors.
*/
#define DEBUG
#include <common.h>
#include <dm.h>
#include <errno.h>
@ -105,8 +105,8 @@ void *phys_to_virt(phys_addr_t paddr)
state = state_get_current();
list_for_each_entry(mentry, &state->mapmem_head, sibling_node) {
if (mentry->tag == paddr) {
printf("%s: Used map from %lx to %p\n", __func__,
(ulong)paddr, mentry->ptr);
debug("%s: Used map from %lx to %p\n", __func__,
(ulong)paddr, mentry->ptr);
return mentry->ptr;
}
}
@ -152,7 +152,7 @@ phys_addr_t virt_to_phys(void *ptr)
__func__, ptr, (ulong)gd->ram_size);
os_abort();
}
printf("%s: Used map from %p to %lx\n", __func__, ptr, mentry->tag);
debug("%s: Used map from %p to %lx\n", __func__, ptr, mentry->tag);
return mentry->tag;
}

View file

@ -98,9 +98,8 @@ void os_exit(int exit_code)
exit(exit_code);
}
int os_write_file(const char *name, const void *buf, int size)
int os_write_file(const char *fname, const void *buf, int size)
{
char fname[256];
int fd;
fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC);
@ -110,14 +109,53 @@ int os_write_file(const char *name, const void *buf, int size)
}
if (os_write(fd, buf, size) != size) {
printf("Cannot write to file '%s'\n", fname);
os_close(fd);
return -EIO;
}
os_close(fd);
printf("Write '%s', size %#x (%d)\n", name, size, size);
return 0;
}
int os_read_file(const char *fname, void **bufp, int *sizep)
{
off_t size;
int ret = -EIO;
int fd;
fd = os_open(fname, OS_O_RDONLY);
if (fd < 0) {
printf("Cannot open file '%s'\n", fname);
goto err;
}
size = os_lseek(fd, 0, OS_SEEK_END);
if (size < 0) {
printf("Cannot seek to end of file '%s'\n", fname);
goto err;
}
if (os_lseek(fd, 0, OS_SEEK_SET) < 0) {
printf("Cannot seek to start of file '%s'\n", fname);
goto err;
}
*bufp = os_malloc(size);
if (!*bufp) {
printf("Not enough memory to read file '%s'\n", fname);
ret = -ENOMEM;
goto err;
}
if (os_read(fd, *bufp, size) != size) {
printf("Cannot read from file '%s'\n", fname);
goto err;
}
os_close(fd);
*sizep = size;
return 0;
err:
os_close(fd);
return ret;
}
/* Restore tty state when we exit */
static struct termios orig_term;
static bool term_setup;

View file

@ -20,6 +20,7 @@
cros_ec: cros-ec {
reg = <0 0>;
u-boot,dm-pre-reloc;
compatible = "google,cros-ec-sandbox";
/*
@ -27,6 +28,7 @@
* that the STM32L flash erases to 0, not 0xff.
*/
flash {
u-boot,dm-pre-reloc;
image-pos = <0x08000000>;
size = <0x20000>;
erase-value = <0>;
@ -59,6 +61,7 @@
};
gpio_a: gpios@0 {
u-boot,dm-pre-reloc;
gpio-controller;
compatible = "sandbox,gpio";
#gpio-cells = <1>;
@ -67,6 +70,7 @@
};
gpio_b: gpios@1 {
u-boot,dm-pre-reloc;
gpio-controller;
compatible = "sandbox,gpio";
#gpio-cells = <2>;
@ -178,12 +182,14 @@
};
spi@0 {
u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0>;
compatible = "sandbox,spi";
cs-gpios = <0>, <&gpio_a 0>;
firmware_storage_spi: flash@0 {
u-boot,dm-pre-reloc;
reg = <0>;
compatible = "spansion,m25p16", "sandbox,spi-flash";
spi-max-frequency = <40000000>;
@ -239,6 +245,7 @@
};
tpm {
u-boot,dm-pre-reloc;
compatible = "google,sandbox-tpm";
};
@ -256,6 +263,7 @@
/* Needs to be available prior to relocation */
uart0: serial {
u-boot,dm-spl;
compatible = "sandbox,serial";
sandbox,text-colour = "cyan";
pinctrl-names = "default";
@ -350,3 +358,10 @@
#include "cros-ec-keyboard.dtsi"
#include "sandbox_pmic.dtsi"
&cros_ec {
u-boot,dm-pre-reloc;
keyboard-controller {
u-boot,dm-pre-reloc;
};
};

View file

@ -113,4 +113,12 @@ int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen);
int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp,
uint *duty_nsp, bool *enablep, bool *polarityp);
/**
* sandbox_sf_set_block_protect() - Set the BP bits of the status register
*
* @dev: Device to update
* @bp_mask: BP bits to set (bits 2:0, so a value of 0 to 7)
*/
void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask);
#endif

View file

@ -306,14 +306,16 @@ int checkboard(void)
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
stdio_print_current_devices();
struct udevice *dev;
int ret;
if (cros_ec_get_error()) {
stdio_print_current_devices();
ret = uclass_first_device_err(UCLASS_CROS_EC, &dev);
if (ret && ret != -ENODEV) {
/* Force console on */
gd->flags &= ~GD_FLG_SILENT;
printf("cros-ec communications failure %d\n",
cros_ec_get_error());
printf("cros-ec communications failure %d\n", ret);
puts("\nPlease reset with Power+Refresh\n\n");
panic("Cannot init cros-ec device");
return -1;

View file

@ -247,25 +247,28 @@ sudo /path/to/u-boot -D
DHCP
....
set autoload no
set ethact eth1
setenv autoload no
setenv ethrotate no
setenv ethact eth1
dhcp
PING
....
set autoload no
set ethact eth1
setenv autoload no
setenv ethrotate no
setenv ethact eth1
dhcp
ping $gatewayip
TFTP
....
set autoload no
set ethact eth1
setenv autoload no
setenv ethrotate no
setenv ethact eth1
dhcp
set serverip WWW.XXX.YYY.ZZZ
setenv serverip WWW.XXX.YYY.ZZZ
tftpboot u-boot.bin
The bridge also supports (to a lesser extent) the localhost interface, 'lo'.
@ -287,7 +290,8 @@ operation being tested on the lo interface.
TFTP
....
set ethact eth5
setenv ethrotate no
setenv ethact eth5
tftpboot u-boot.bin

View file

@ -59,12 +59,15 @@ int board_init(void)
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
if (cros_ec_get_error()) {
struct udevice *dev;
int ret;
ret = uclass_first_device_err(UCLASS_CROS_EC, &dev);
if (ret && ret != -ENODEV) {
/* Force console on */
gd->flags &= ~GD_FLG_SILENT;
printf("cros-ec communications failure %d\n",
cros_ec_get_error());
printf("cros-ec communications failure %d\n", ret);
puts("\nPlease reset with Power+Refresh\n\n");
panic("Cannot init cros-ec device");
return -1;

View file

@ -202,7 +202,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
fdt_strerror(err));
return 1;
}
working_fdt = newaddr;
set_working_fdt_addr((ulong)newaddr);
#ifdef CONFIG_OF_SYSTEM_SETUP
/* Call the board-specific fixup routine */
} else if (strncmp(argv[1], "sys", 3) == 0) {

View file

@ -27,6 +27,15 @@ config SPL_BOOTSTAGE
information when SPL finishes and load it when U-Boot proper starts
up.
config TPL_BOOTSTAGE
bool "Boot timing and reported in TPL"
depends on BOOTSTAGE
help
Enable recording of boot time in SPL. To make this visible to U-Boot
proper, enable BOOTSTAGE_STASH as well. This will stash the timing
information when TPL finishes and load it when U-Boot proper starts
up.
config BOOTSTAGE_REPORT
bool "Display a detailed boot timing report before booting the OS"
depends on BOOTSTAGE
@ -444,6 +453,16 @@ config LOG
config SPL_LOG
bool "Enable logging support in SPL"
depends on LOG
help
This enables support for logging of status and debug messages. These
can be displayed on the console, recorded in a memory buffer, or
discarded if not needed. Logging supports various categories and
levels of severity.
config TPL_LOG
bool "Enable logging support in TPL"
depends on LOG
help
This enables support for logging of status and debug messages. These
can be displayed on the console, recorded in a memory buffer, or
@ -660,6 +679,22 @@ config AVB_VERIFY
* Helpers to access MMC, similar to drivers/fastboot/fb_mmc.c.
* Helpers to alloc/init/free avb ops.
config SPL_HASH
bool # "Support hashing API (SHA1, SHA256, etc.)"
help
This provides a way to hash data in memory using various supported
algorithms (such as SHA1, MD5, CRC32). The API is defined in hash.h
and the algorithms it supports are defined in common/hash.c. See
also CMD_HASH for command-line access.
config TPL_HASH
bool # "Support hashing API (SHA1, SHA256, etc.)"
help
This provides a way to hash data in memory using various supported
algorithms (such as SHA1, MD5, CRC32). The API is defined in hash.h
and the algorithms it supports are defined in common/hash.c. See
also CMD_HASH for command-line access.
endmenu
menu "Update support"

View file

@ -68,6 +68,7 @@ obj-$(CONFIG_DFU_OVER_USB) += dfu.o
endif
obj-$(CONFIG_SPL_DFU_SUPPORT) += cli_hush.o
obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o
obj-$(CONFIG_TPL_HASH_SUPPORT) += hash.o
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
@ -76,7 +77,8 @@ ifdef CONFIG_SPL_USB_HOST_SUPPORT
obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
obj-$(CONFIG_USB_STORAGE) += usb_storage.o
endif
endif
endif # CONFIG_SPL_BUILD
#others
obj-$(CONFIG_DDR_SPD) += ddr_spd.o
obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o
@ -90,14 +92,16 @@ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o
endif
else
obj-y += console.o
endif
endif # CONFIG_SPL_BUILD
obj-$(CONFIG_CROS_EC) += cros_ec.o
obj-y += dlmalloc.o
ifdef CONFIG_SYS_MALLOC_F
ifneq ($(CONFIG_$(SPL_)SYS_MALLOC_F_LEN),0)
ifneq ($(CONFIG_$(SPL_TPL_)SYS_MALLOC_F_LEN),0)
obj-y += malloc_simple.o
endif
endif
obj-y += image.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o

View file

@ -25,15 +25,3 @@ struct udevice *board_get_cros_ec_dev(void)
}
return dev;
}
int cros_ec_get_error(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
if (ret && ret != -ENODEV)
return ret;
return 0;
}

View file

@ -29,7 +29,7 @@ static ulong vexpress_osc_clk_get_rate(struct clk *clk)
data = CLK_FUNCTION | priv->osc;
err = misc_read(vexpress_cfg, 0, &data, sizeof(data));
if (err)
if (err < 0)
return err;
return data;
@ -53,7 +53,7 @@ static ulong vexpress_osc_clk_set_rate(struct clk *clk, ulong rate)
buffer[0] = CLK_FUNCTION | priv->osc;
buffer[1] = rate;
err = misc_write(vexpress_cfg, 0, buffer, 2 * sizeof(u32));
if (err)
if (err < 0)
return err;
return rate;

View file

@ -15,8 +15,8 @@ static void show_devices(struct udevice *dev, int depth, int last_flag)
int i, is_last;
struct udevice *child;
/* print the first 11 characters to not break the tree-format. */
printf(" %-10.10s %d [ %c ] %-10.10s ", dev->uclass->uc_drv->name,
/* print the first 20 characters to not break the tree-format. */
printf(" %-10.10s %d [ %c ] %-20.20s ", dev->uclass->uc_drv->name,
dev_get_uclass_index(dev, NULL),
dev->flags & DM_FLAG_ACTIVATED ? '+' : ' ', dev->driver->name);
@ -49,8 +49,8 @@ void dm_dump_all(void)
root = dm_root();
if (root) {
printf(" Class index Probed Driver Name\n");
printf("-----------------------------------------\n");
printf(" Class index Probed Driver Name\n");
printf("-----------------------------------------------------------\n");
show_devices(root, -1, 0);
}
}

View file

@ -35,7 +35,7 @@ void display_sysid(void)
if (ret)
return;
ret = misc_read(dev, 0, &sysid, sizeof(sysid));
if (ret)
if (ret < 0)
return;
stamp = sysid[1];

View file

@ -13,6 +13,8 @@
* is not reset.
*/
#define LOG_CATEGORY UCLASS_CROS_EC
#include <common.h>
#include <command.h>
#include <dm.h>
@ -41,6 +43,54 @@ enum {
CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
};
#define INVALID_HCMD 0xFF
/*
* Map UHEPI masks to non UHEPI commands in order to support old EC FW
* which does not support UHEPI command.
*/
static const struct {
u8 set_cmd;
u8 clear_cmd;
u8 get_cmd;
} event_map[] = {
[EC_HOST_EVENT_MAIN] = {
INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR,
INVALID_HCMD,
},
[EC_HOST_EVENT_B] = {
INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR_B,
EC_CMD_HOST_EVENT_GET_B,
},
[EC_HOST_EVENT_SCI_MASK] = {
EC_CMD_HOST_EVENT_SET_SCI_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_SCI_MASK,
},
[EC_HOST_EVENT_SMI_MASK] = {
EC_CMD_HOST_EVENT_SET_SMI_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_SMI_MASK,
},
[EC_HOST_EVENT_ALWAYS_REPORT_MASK] = {
INVALID_HCMD, INVALID_HCMD, INVALID_HCMD,
},
[EC_HOST_EVENT_ACTIVE_WAKE_MASK] = {
EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_WAKE_MASK,
},
[EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX] = {
EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_WAKE_MASK,
},
[EC_HOST_EVENT_LAZY_WAKE_MASK_S3] = {
EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_WAKE_MASK,
},
[EC_HOST_EVENT_LAZY_WAKE_MASK_S5] = {
EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
EC_CMD_HOST_EVENT_GET_WAKE_MASK,
},
};
void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len)
{
#ifdef DEBUG
@ -227,7 +277,7 @@ static int send_command_proto3(struct cros_ec_dev *cdev,
return handle_proto3_response(cdev, dinp, din_len);
}
static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
static int send_command(struct cros_ec_dev *dev, uint cmd, int cmd_version,
const void *dout, int dout_len,
uint8_t **dinp, int din_len)
{
@ -330,7 +380,7 @@ static int ec_command_inptr(struct udevice *dev, uint8_t cmd,
* @param din_len Maximum size of response in bytes
* @return number of bytes in response, or -ve on error
*/
static int ec_command(struct udevice *dev, uint8_t cmd, int cmd_version,
static int ec_command(struct udevice *dev, uint cmd, int cmd_version,
const void *dout, int dout_len,
void *din, int din_len)
{
@ -365,10 +415,14 @@ int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan)
int cros_ec_read_id(struct udevice *dev, char *id, int maxlen)
{
struct ec_response_get_version *r;
int ret;
if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
(uint8_t **)&r, sizeof(*r)) != sizeof(*r))
ret = ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
(uint8_t **)&r, sizeof(*r));
if (ret != sizeof(*r)) {
log_err("Got rc %d, expected %d\n", ret, sizeof(*r));
return -1;
}
if (maxlen > (int)sizeof(r->version_string_ro))
maxlen = sizeof(r->version_string_ro);
@ -381,6 +435,7 @@ int cros_ec_read_id(struct udevice *dev, char *id, int maxlen)
memcpy(id, r->version_string_rw, maxlen);
break;
default:
log_err("Invalid EC image %d\n", r->current_image);
return -1;
}
@ -563,6 +618,36 @@ int cros_ec_info(struct udevice *dev, struct ec_response_mkbp_info *info)
return 0;
}
int cros_ec_get_event_mask(struct udevice *dev, uint type, uint32_t *mask)
{
struct ec_response_host_event_mask rsp;
int ret;
ret = ec_command(dev, type, 0, NULL, 0, &rsp, sizeof(rsp));
if (ret < 0)
return ret;
else if (ret != sizeof(rsp))
return -EINVAL;
*mask = rsp.mask;
return 0;
}
int cros_ec_set_event_mask(struct udevice *dev, uint type, uint32_t mask)
{
struct ec_params_host_event_mask req;
int ret;
req.mask = mask;
ret = ec_command(dev, type, 0, &req, sizeof(req), NULL, 0);
if (ret < 0)
return ret;
return 0;
}
int cros_ec_get_host_events(struct udevice *dev, uint32_t *events_ptr)
{
struct ec_response_host_event_mask *resp;
@ -616,6 +701,17 @@ int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask,
return 0;
}
int cros_ec_entering_mode(struct udevice *dev, int mode)
{
int rc;
rc = ec_command(dev, EC_CMD_ENTERING_MODE, 0, &mode, sizeof(mode),
NULL, 0);
if (rc)
return -1;
return 0;
}
static int cros_ec_check_version(struct udevice *dev)
{
struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
@ -650,16 +746,14 @@ static int cros_ec_check_version(struct udevice *dev)
cdev->protocol_version = 3;
req.in_data = 0;
if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
(uint8_t **)&resp, sizeof(*resp)) > 0) {
(uint8_t **)&resp, sizeof(*resp)) > 0)
return 0;
}
/* Try sending a version 2 packet */
cdev->protocol_version = 2;
if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
(uint8_t **)&resp, sizeof(*resp)) > 0) {
(uint8_t **)&resp, sizeof(*resp)) > 0)
return 0;
}
/*
* Fail if we're still here, since the EC doesn't understand any
@ -822,6 +916,9 @@ int cros_ec_flash_write(struct udevice *dev, const uint8_t *data,
uint32_t end, off;
int ret;
if (!burst)
return -EINVAL;
/*
* TODO: round up to the nearest multiple of write size. Can get away
* without that on link right now because its write size is 4 bytes.
@ -844,6 +941,35 @@ int cros_ec_flash_write(struct udevice *dev, const uint8_t *data,
return 0;
}
/**
* Run verification on a slot
*
* @param me CrosEc instance
* @param region Region to run verification on
* @return 0 if success or not applicable. Non-zero if verification failed.
*/
int cros_ec_efs_verify(struct udevice *dev, enum ec_flash_region region)
{
struct ec_params_efs_verify p;
int rv;
log_info("EFS: EC is verifying updated image...\n");
p.region = region;
rv = ec_command(dev, EC_CMD_EFS_VERIFY, 0, &p, sizeof(p), NULL, 0);
if (rv >= 0) {
log_info("EFS: Verification success\n");
return 0;
}
if (rv == -EC_RES_INVALID_COMMAND) {
log_info("EFS: EC doesn't support EFS_VERIFY command\n");
return 0;
}
log_info("EFS: Verification failed\n");
return rv;
}
/**
* Read a single block from the flash
*
@ -934,15 +1060,17 @@ int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size)
struct ec_params_vbnvcontext p;
int len;
if (size != EC_VBNV_BLOCK_SIZE)
if (size != EC_VBNV_BLOCK_SIZE && size != EC_VBNV_BLOCK_SIZE_V2)
return -EINVAL;
p.op = EC_VBNV_CONTEXT_OP_READ;
len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
&p, sizeof(p), block, EC_VBNV_BLOCK_SIZE);
if (len < EC_VBNV_BLOCK_SIZE)
&p, sizeof(uint32_t) + size, block, size);
if (len != size) {
log_err("Expected %d bytes, got %d\n", size, len);
return -EIO;
}
return 0;
}
@ -952,19 +1080,33 @@ int cros_ec_write_nvdata(struct udevice *dev, const uint8_t *block, int size)
struct ec_params_vbnvcontext p;
int len;
if (size != EC_VBNV_BLOCK_SIZE)
if (size != EC_VBNV_BLOCK_SIZE && size != EC_VBNV_BLOCK_SIZE_V2)
return -EINVAL;
p.op = EC_VBNV_CONTEXT_OP_WRITE;
memcpy(p.block, block, sizeof(p.block));
memcpy(p.block, block, size);
len = ec_command_inptr(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
&p, sizeof(p), NULL, 0);
&p, sizeof(uint32_t) + size, NULL, 0);
if (len < 0)
return -1;
return 0;
}
int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags)
{
struct ec_params_battery_cutoff p;
int len;
p.flags = flags;
len = ec_command(dev, EC_CMD_BATTERY_CUT_OFF, 1, &p, sizeof(p),
NULL, 0);
if (len < 0)
return -1;
return 0;
}
int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state)
{
struct ec_params_ldo_set params;
@ -1139,9 +1281,209 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
return 0;
}
int cros_ec_check_feature(struct udevice *dev, int feature)
{
struct ec_response_get_features r;
int rv;
rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0);
if (rv)
return rv;
if (feature >= 8 * sizeof(r.flags))
return -1;
return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature);
}
/*
* Query the EC for specified mask indicating enabled events.
* The EC maintains separate event masks for SMI, SCI and WAKE.
*/
static int cros_ec_uhepi_cmd(struct udevice *dev, uint mask, uint action,
uint64_t *value)
{
int ret;
struct ec_params_host_event req;
struct ec_response_host_event rsp;
req.action = action;
req.mask_type = mask;
if (action != EC_HOST_EVENT_GET)
req.value = *value;
else
*value = 0;
ret = ec_command(dev, EC_CMD_HOST_EVENT, 0, &req, sizeof(req), &rsp,
sizeof(rsp));
if (action != EC_HOST_EVENT_GET)
return ret;
if (ret == 0)
*value = rsp.value;
return ret;
}
static int cros_ec_handle_non_uhepi_cmd(struct udevice *dev, uint hcmd,
uint action, uint64_t *value)
{
int ret = -1;
struct ec_params_host_event_mask req;
struct ec_response_host_event_mask rsp;
if (hcmd == INVALID_HCMD)
return ret;
if (action != EC_HOST_EVENT_GET)
req.mask = (uint32_t)*value;
else
*value = 0;
ret = ec_command(dev, hcmd, 0, &req, sizeof(req), &rsp, sizeof(rsp));
if (action != EC_HOST_EVENT_GET)
return ret;
if (ret == 0)
*value = rsp.mask;
return ret;
}
bool cros_ec_is_uhepi_supported(struct udevice *dev)
{
#define UHEPI_SUPPORTED 1
#define UHEPI_NOT_SUPPORTED 2
static int uhepi_support;
if (!uhepi_support) {
uhepi_support = cros_ec_check_feature(dev,
EC_FEATURE_UNIFIED_WAKE_MASKS) > 0 ? UHEPI_SUPPORTED :
UHEPI_NOT_SUPPORTED;
log_debug("Chrome EC: UHEPI %s\n",
uhepi_support == UHEPI_SUPPORTED ? "supported" :
"not supported");
}
return uhepi_support == UHEPI_SUPPORTED;
}
static int cros_ec_get_mask(struct udevice *dev, uint type)
{
u64 value = 0;
if (cros_ec_is_uhepi_supported(dev)) {
cros_ec_uhepi_cmd(dev, type, EC_HOST_EVENT_GET, &value);
} else {
assert(type < ARRAY_SIZE(event_map));
cros_ec_handle_non_uhepi_cmd(dev, event_map[type].get_cmd,
EC_HOST_EVENT_GET, &value);
}
return value;
}
static int cros_ec_clear_mask(struct udevice *dev, uint type, u64 mask)
{
if (cros_ec_is_uhepi_supported(dev))
return cros_ec_uhepi_cmd(dev, type, EC_HOST_EVENT_CLEAR, &mask);
assert(type < ARRAY_SIZE(event_map));
return cros_ec_handle_non_uhepi_cmd(dev, event_map[type].clear_cmd,
EC_HOST_EVENT_CLEAR, &mask);
}
uint64_t cros_ec_get_events_b(struct udevice *dev)
{
return cros_ec_get_mask(dev, EC_HOST_EVENT_B);
}
int cros_ec_clear_events_b(struct udevice *dev, uint64_t mask)
{
log_debug("Chrome EC: clear events_b mask to 0x%016llx\n", mask);
return cros_ec_clear_mask(dev, EC_HOST_EVENT_B, mask);
}
int cros_ec_read_limit_power(struct udevice *dev, int *limit_powerp)
{
struct ec_params_charge_state p;
struct ec_response_charge_state r;
int ret;
p.cmd = CHARGE_STATE_CMD_GET_PARAM;
p.get_param.param = CS_PARAM_LIMIT_POWER;
ret = ec_command(dev, EC_CMD_CHARGE_STATE, 0, &p, sizeof(p),
&r, sizeof(r));
/*
* If our EC doesn't support the LIMIT_POWER parameter, assume that
* LIMIT_POWER is not requested.
*/
if (ret == -EC_RES_INVALID_PARAM || ret == -EC_RES_INVALID_COMMAND) {
log_warning("PARAM_LIMIT_POWER not supported by EC\n");
return -ENOSYS;
}
if (ret != sizeof(r.get_param))
return -EINVAL;
*limit_powerp = r.get_param.value;
return 0;
}
int cros_ec_config_powerbtn(struct udevice *dev, uint32_t flags)
{
struct ec_params_config_power_button params;
int ret;
params.flags = flags;
ret = ec_command(dev, EC_CMD_CONFIG_POWER_BUTTON, 0,
&params, sizeof(params), NULL, 0);
if (ret < 0)
return ret;
return 0;
}
int cros_ec_get_lid_shutdown_mask(struct udevice *dev)
{
u32 mask;
int ret;
ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK,
&mask);
if (ret < 0)
return ret;
return !!(mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED));
}
int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
{
u32 mask;
int ret;
ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK,
&mask);
if (ret < 0)
return ret;
// Set lid close event state in the EC SMI event mask
if (enable)
mask |= EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED);
else
mask &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED);
ret = cros_ec_set_event_mask(dev, EC_CMD_HOST_EVENT_SET_SMI_MASK, mask);
if (ret < 0)
return ret;
printf("EC: %sabled lid close event\n", enable ? "en" : "dis");
return 0;
}
UCLASS_DRIVER(cros_ec) = {
.id = UCLASS_CROS_EC,
.name = "cros_ec",
.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
.post_bind = dm_scan_fdt_dev,
.flags = DM_UC_FLAG_ALLOC_PRIV_DMA,
};

View file

@ -74,7 +74,7 @@ struct ec_keymatrix_entry {
* @recovery_req: Keyboard recovery requested
*/
struct ec_state {
uint8_t vbnv_context[EC_VBNV_BLOCK_SIZE];
u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
struct fdt_cros_ec ec_config;
uint8_t *flash_data;
int flash_data_len;

View file

@ -20,7 +20,7 @@ int misc_sandbox_read(struct udevice *dev, int offset, void *buf, int size)
memcpy(buf, priv->mem + offset, size);
return 0;
return size;
}
int misc_sandbox_write(struct udevice *dev, int offset, const void *buf,
@ -30,7 +30,7 @@ int misc_sandbox_write(struct udevice *dev, int offset, const void *buf,
memcpy(priv->mem + offset, buf, size);
return 0;
return size;
}
int misc_sandbox_ioctl(struct udevice *dev, unsigned long request, void *buf)

View file

@ -65,7 +65,7 @@ static int dump_efuses(cmd_tbl_t *cmdtp, int flag,
}
ret = misc_read(dev, 0, &fuses, sizeof(fuses));
if (ret) {
if (ret < 0) {
printf("%s: misc_read failed\n", __func__);
return 0;
}

View file

@ -29,6 +29,9 @@ int fuse_read(u32 bank, u32 word, u32 *val)
return ret;
ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
val, 4);
if (ret < 0)
return ret;
ret = 0;
break;
default:
@ -54,6 +57,9 @@ int fuse_prog(u32 bank, u32 word, u32 val)
return ret;
ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET,
&val, 4);
if (ret < 0)
return ret;
ret = 0;
break;
default:
@ -78,6 +84,9 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
if (ret)
return ret;
ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4);
if (ret < 0)
return ret;
ret = 0;
break;
default:
@ -103,6 +112,9 @@ int fuse_override(u32 bank, u32 word, u32 val)
return ret;
ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
&val, 4);
if (ret < 0)
return ret;
ret = 0;
break;
default:

View file

@ -57,6 +57,8 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
/* Bits for the status register */
#define STAT_WIP (1 << 0)
#define STAT_WEL (1 << 1)
#define STAT_BP_SHIFT 2
#define STAT_BP_MASK (7 << STAT_BP_SHIFT)
/* Assume all SPI flashes have 3 byte addresses since they do atm */
#define SF_ADDR_LEN 3
@ -102,6 +104,14 @@ struct sandbox_spi_flash_plat_data {
int cs;
};
void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask)
{
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
sbsf->status &= ~STAT_BP_MASK;
sbsf->status |= bp_mask << STAT_BP_SHIFT;
}
/**
* This is a very strange probe function. If it has platform data (which may
* have come from the device tree) then this function gets the filename and

View file

@ -28,6 +28,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)
return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
}
int spl_flash_get_sw_write_prot(struct udevice *dev)
{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_sw_write_prot)
return -ENOSYS;
return log_ret(ops->get_sw_write_prot(dev));
}
/*
* TODO(sjg@chromium.org): This is an old-style function. We should remove
* it when all SPI flash drivers use dm

View file

@ -170,6 +170,9 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
/* Flash erase(sectors) operation, support all possible erase commands */
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
/* Get software write-protect value (BP bits) */
int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
/* Lock stmicro spi flash region */
int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);

View file

@ -124,6 +124,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
return spi_flash_cmd_erase_ops(flash, offset, len);
}
static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
{
struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_get_sw_write_prot(flash);
}
static int spi_flash_std_probe(struct udevice *dev)
{
struct spi_slave *slave = dev_get_parent_priv(dev);
@ -141,6 +148,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = {
.read = spi_flash_std_read,
.write = spi_flash_std_write,
.erase = spi_flash_std_erase,
.get_sw_write_prot = spi_flash_std_get_sw_write_prot,
};
static const struct udevice_id spi_flash_std_ids[] = {

View file

@ -110,6 +110,18 @@ static int write_cr(struct spi_flash *flash, u8 wc)
}
#endif
int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash)
{
u8 status;
int ret;
ret = read_sr(flash, &status);
if (ret)
return ret;
return (status >> 2) & 7;
}
#ifdef CONFIG_SPI_FLASH_BAR
/*
* This "clean_bar" is necessary in a situation when one was accessing

View file

@ -774,16 +774,19 @@ int pci_bind_bus_devices(struct udevice *bus)
found_multi = false;
if (PCI_FUNC(bdf) && !found_multi)
continue;
/* Check only the first access, we don't expect problems */
ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
&header_type, PCI_SIZE_8);
ret = pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
PCI_SIZE_16);
if (ret)
goto error;
pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
PCI_SIZE_16);
if (vendor == 0xffff || vendor == 0x0000)
continue;
pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
&header_type, PCI_SIZE_8);
if (!PCI_FUNC(bdf))
found_multi = header_type & 0x80;

View file

@ -15,6 +15,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define SPI_DEFAULT_SPEED_HZ 100000
static int spi_set_speed_mode(struct udevice *bus, int speed, int mode)
{
struct dm_spi_ops *ops;
@ -58,7 +60,7 @@ int dm_spi_claim_bus(struct udevice *dev)
speed = spi->max_hz;
}
if (!speed)
speed = 100000;
speed = SPI_DEFAULT_SPEED_HZ;
if (speed != slave->speed) {
int ret = spi_set_speed_mode(bus, speed, slave->mode);
@ -300,7 +302,13 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
}
plat = dev_get_parent_platdata(dev);
plat->cs = cs;
plat->max_hz = speed;
if (speed) {
plat->max_hz = speed;
} else {
printf("Warning: SPI speed fallback to %u kHz\n",
SPI_DEFAULT_SPEED_HZ / 1000);
plat->max_hz = SPI_DEFAULT_SPEED_HZ;
}
plat->mode = mode;
created = true;
} else if (ret) {
@ -374,7 +382,8 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev,
int value;
plat->cs = dev_read_u32_default(dev, "reg", -1);
plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency", 0);
plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency",
SPI_DEFAULT_SPEED_HZ);
if (dev_read_bool(dev, "spi-cpol"))
mode |= SPI_CPOL;
if (dev_read_bool(dev, "spi-cpha"))

View file

@ -187,9 +187,11 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
code = get_unaligned_be32(sendbuf + sizeof(uint16_t) +
sizeof(uint32_t));
#ifdef DEBUG
printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size,
*recv_len, code);
print_buffer(0, sendbuf, 1, send_size, 0);
#endif
switch (code) {
case TPM_CMD_GET_CAPABILITY:
type = get_unaligned_be32(sendbuf + 14);
@ -306,6 +308,10 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
printf("Unknown tpm command %02x\n", code);
return -ENOSYS;
}
#ifdef DEBUG
printf("tpm: rx recv_len %zd\n", *recv_len);
print_buffer(0, recvbuf, 1, *recv_len, 0);
#endif
return 0;
}

View file

@ -344,7 +344,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
switch (val) {
case 0:
/* all attributes off */
video_set_default_colors(vid_priv);
video_set_default_colors(dev->parent, false);
break;
case 1:
/* bold */

View file

@ -115,18 +115,29 @@ int video_clear(struct udevice *dev)
return 0;
}
void video_set_default_colors(struct video_priv *priv)
void video_set_default_colors(struct udevice *dev, bool invert)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
int fore, back;
#ifdef CONFIG_SYS_WHITE_ON_BLACK
/* White is used when switching to bold, use light gray here */
priv->fg_col_idx = VID_LIGHT_GRAY;
priv->colour_fg = vid_console_color(priv, VID_LIGHT_GRAY);
priv->colour_bg = vid_console_color(priv, VID_BLACK);
fore = VID_LIGHT_GRAY;
back = VID_BLACK;
#else
priv->fg_col_idx = VID_BLACK;
priv->colour_fg = vid_console_color(priv, VID_BLACK);
priv->colour_bg = vid_console_color(priv, VID_WHITE);
fore = VID_BLACK;
back = VID_WHITE;
#endif
if (invert) {
int temp;
temp = fore;
fore = back;
back = temp;
}
priv->fg_col_idx = fore;
priv->colour_fg = vid_console_color(priv, fore);
priv->colour_bg = vid_console_color(priv, back);
}
/* Flush video activity to the caches */
@ -219,7 +230,7 @@ static int video_post_probe(struct udevice *dev)
priv->fb_size = priv->line_length * priv->ysize;
/* Set up colors */
video_set_default_colors(priv);
video_set_default_colors(dev, false);
if (!CONFIG_IS_ENABLED(NO_FB_CLEAR))
video_clear(dev);

View file

@ -187,6 +187,14 @@ int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask,
uint32_t set_flags,
struct ec_response_flash_protect *resp);
/**
* Notify EC of current boot mode
*
* @param dev CROS-EC device
* @param vboot_mode Verified boot mode
* @return 0 if ok, <0 on error
*/
int cros_ec_entering_mode(struct udevice *dev, int mode);
/**
* Run internal tests on the cros_ec interface.
@ -397,4 +405,85 @@ struct i2c_msg;
int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *msg,
int nmsgs);
/**
* cros_ec_get_events_b() - Get event mask B
*
* @return value of event mask, default value of 0 if it could not be read
*/
uint64_t cros_ec_get_events_b(struct udevice *dev);
/**
* cros_ec_clear_events_b() - Clear even mask B
*
* Any pending events in the B range are cleared
*
* @return 0 if OK, -ve on error
*/
int cros_ec_clear_events_b(struct udevice *dev, uint64_t mask);
/**
* cros_ec_efs_verify() - tell the EC to verify one of its images
*
* @param dev CROS-EC device
* @param region Flash region to query
* @return 0 if OK, -ve on error
*/
int cros_ec_efs_verify(struct udevice *dev, enum ec_flash_region region);
/**
* cros_ec_battery_cutoff() - Request that the battery be cut off
*
* This tells the battery to stop supplying power. This is used before shipping
* a device to ensure that the battery remains charged while the device is
* shipped or sitting on the shelf waiting to be purchased.
*
* @param dev CROS-EC device
* @param flags Flags to use (EC_BATTERY_CUTOFF_FLAG_...)
* @return 0 if OK, -ve on error
*/
int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags);
/**
* cros_ec_read_limit_power() - Check if power is limited by batter/charger
*
* Sometimes the battery is low and / or the device is connected to a charger
* that cannot supply much power.
*
* @param dev CROS-EC device
* @param limit_powerp Returns whether power is limited (0 or 1)
* @return 0 if OK, -ENOSYS if the EC does not support this comment, -EINVAL
* if the EC returned an invalid response
*/
int cros_ec_read_limit_power(struct udevice *dev, int *limit_powerp);
/**
* cros_ec_config_powerbtn() - Configure the behaviour of the power button
*
* @param dev CROS-EC device
* @param flags Flags to use (EC_POWER_BUTTON_...)
* @return 0 if OK, -ve on error
*/
int cros_ec_config_powerbtn(struct udevice *dev, uint32_t flags);
/**
* cros_ec_get_lid_shutdown_mask() - Set the lid shutdown mask
*
* Determines whether a lid close event is reported
*
* @param dev CROS-EC device
* @return shufdown mas if OK, -ve on error
*/
int cros_ec_get_lid_shutdown_mask(struct udevice *dev);
/**
* cros_ec_set_lid_shutdown_mask() - Set the lid shutdown mask
*
* Set whether a lid close event is reported
*
* @param dev CROS-EC device
* @param enable true to enable reporting, false to disable
* @return shufdown mas if OK, -ve on error
*/
int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable);
#endif

View file

@ -956,6 +956,7 @@ int fdtdec_setup(void);
* Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined
* and the board implements it.
*/
void *board_fdt_blob_setup(void);
/*
* Decode the size of memory

View file

@ -47,6 +47,7 @@ enum log_category_t {
LOGC_DT, /* Device-tree */
LOGC_EFI, /* EFI implementation */
LOGC_ALLOC, /* Memory allocation */
LOGC_SANDBOX, /* Related to the sandbox board */
LOGC_COUNT, /* Number of log categories */
LOGC_END, /* Sentinel value for a list of log categories */

View file

@ -13,7 +13,7 @@
* @buf: pointer to data buffer
* @size: data size in bytes to read the device
*
* Return: 0 if OK, -ve on error
* Return: number of bytes read if OK (may be 0 if EOF), -ve on error
*/
int misc_read(struct udevice *dev, int offset, void *buf, int size);
@ -24,7 +24,7 @@ int misc_read(struct udevice *dev, int offset, void *buf, int size);
* @buf: pointer to data buffer
* @size: data size in bytes to write the device
*
* Return: 0 if OK, -ve on error
* Return: number of bytes written if OK (may be < @size), -ve on error
*/
int misc_write(struct udevice *dev, int offset, void *buf, int size);
@ -90,7 +90,7 @@ struct misc_ops {
* @buf: pointer to data buffer
* @size: data size in bytes to read the device
*
* Return: 0 if OK, -ve on error
* Return: number of bytes read if OK (may be 0 if EOF), -ve on error
*/
int (*read)(struct udevice *dev, int offset, void *buf, int size);
@ -101,7 +101,7 @@ struct misc_ops {
* @buf: pointer to data buffer
* @size: data size in bytes to write the device
*
* Return: 0 if OK, -ve on error
* Return: number of bytes written if OK (may be < @size), -ve on error
*/
int (*write)(struct udevice *dev, int offset, const void *buf,
int size);

View file

@ -350,4 +350,18 @@ int os_mprotect_allow(void *start, size_t len);
*/
int os_write_file(const char *name, const void *buf, int size);
/**
* os_read_file() - Read a file from the host filesystem
*
* This can be useful when reading test data into sandbox for use by test
* routines. The data is allocated using os_malloc() and should be freed by
* the caller.
*
* @name: File path to read from
* @bufp: Returns buffer containing data read
* @sizep: Returns size of data
* @return 0 if OK, -ve on error
*/
int os_read_file(const char *name, void **bufp, int *sizep);
#endif

View file

@ -112,6 +112,19 @@ struct dm_spi_flash_ops {
int (*write)(struct udevice *dev, u32 offset, size_t len,
const void *buf);
int (*erase)(struct udevice *dev, u32 offset, size_t len);
/**
* get_sw_write_prot() - Check state of software write-protect feature
*
* SPI flash chips can lock a region of the flash defined by a
* 'protected area'. This function checks if this protected area is
* defined.
*
* @dev: SPI flash device
* @return 0 if no region is write-protected, 1 if a region is
* write-protected, -ENOSYS if the driver does not implement this,
* other -ve value on error
*/
int (*get_sw_write_prot)(struct udevice *dev);
};
/* Access the serial operations for a device */
@ -153,6 +166,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,
*/
int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
/**
* spl_flash_get_sw_write_prot() - Check state of software write-protect feature
*
* SPI flash chips can lock a region of the flash defined by a
* 'protected area'. This function checks if this protected area is
* defined.
*
* @dev: SPI flash device
* @return 0 if no region is write-protected, 1 if a region is
* write-protected, -ENOSYS if the driver does not implement this,
* other -ve value on error
*/
int spl_flash_get_sw_write_prot(struct udevice *dev);
int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode,
struct udevice **devp);

View file

@ -191,9 +191,10 @@ void video_set_flush_dcache(struct udevice *dev, bool flush);
/**
* Set default colors and attributes
*
* @priv device information
* @dev: video device
* @invert true to invert colours
*/
void video_set_default_colors(struct video_priv *priv);
void video_set_default_colors(struct udevice *dev, bool invert);
#endif /* CONFIG_DM_VIDEO */

View file

@ -301,6 +301,14 @@ config LZO
help
This enables support for LZO compression algorithm.r
config SPL_LZ4
bool "Enable LZ4 decompression support in SPL"
help
This enables support for tge LZ4 decompression algorithm in SPL. LZ4
is a lossless data compression algorithm that is focused on
fast compression and decompression speed. It belongs to the LZ77
family of byte-oriented compression schemes.
config SPL_LZO
bool "Enable LZO decompression support in SPL"
help

View file

@ -38,7 +38,6 @@ obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
obj-y += initcall.o
obj-$(CONFIG_LMB) += lmb.o
obj-y += ldiv.o
obj-$(CONFIG_LZ4) += lz4_wrapper.o
obj-$(CONFIG_MD5) += md5.o
obj-y += net_utils.o
obj-$(CONFIG_PHYSMEM) += physmem.o
@ -64,6 +63,7 @@ obj-$(CONFIG_SHA256) += sha256.o
obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
obj-$(CONFIG_$(SPL_)LZO) += lzo/
obj-$(CONFIG_$(SPL_)LZ4) += lz4_wrapper.o
obj-$(CONFIG_LIBAVB) += libavb/

View file

@ -1198,7 +1198,8 @@ static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
# else
static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
{
return -ENOTSUPP;
*dstp = (void *)src;
return 0;
}
# endif
#endif

View file

@ -15,6 +15,7 @@
* reentrant and should be faster). Use only strsep() in new code, please.
*/
#include <config.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ctype.h>

View file

@ -21,9 +21,9 @@ static int dm_test_misc(struct unit_test_state *uts)
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "misc-test", &dev));
/* Read / write tests */
ut_assertok(misc_write(dev, 0, "TEST", 4));
ut_assertok(misc_write(dev, 4, "WRITE", 5));
ut_assertok(misc_read(dev, 0, buf, 9));
ut_asserteq(4, misc_write(dev, 0, "TEST", 4));
ut_asserteq(5, misc_write(dev, 4, "WRITE", 5));
ut_asserteq(9, misc_read(dev, 0, buf, 9));
ut_assertok(memcmp(buf, "TESTWRITE", 9));

View file

@ -6,15 +6,66 @@
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <mapmem.h>
#include <os.h>
#include <spi.h>
#include <spi_flash.h>
#include <asm/state.h>
#include <asm/test.h>
#include <dm/test.h>
#include <dm/util.h>
#include <test/ut.h>
/* Test that sandbox SPI flash works correctly */
/* Simple test of sandbox SPI flash */
static int dm_test_spi_flash(struct unit_test_state *uts)
{
struct udevice *dev, *emul;
int full_size = 0x200000;
int size = 0x10000;
u8 *src, *dst;
int i;
src = map_sysmem(0x20000, full_size);
ut_assertok(os_write_file("spi.bin", src, full_size));
ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev));
dst = map_sysmem(0x20000 + full_size, full_size);
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
ut_assertok(memcmp(src, dst, size));
/* Erase */
ut_assertok(spi_flash_erase_dm(dev, 0, size));
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
for (i = 0; i < size; i++)
ut_asserteq(dst[i], 0xff);
/* Write some new data */
for (i = 0; i < size; i++)
src[i] = i;
ut_assertok(spi_flash_write_dm(dev, 0, size, src));
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
ut_assertok(memcmp(src, dst, size));
/* Try the write-protect stuff */
ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul));
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
sandbox_sf_set_block_protect(emul, 1);
ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
sandbox_sf_set_block_protect(emul, 0);
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
/*
* Since we are about to destroy all devices, we must tell sandbox
* to forget the emulation device
*/
sandbox_sf_unbind_emul(state_get_current(), 0, 0);
return 0;
}
DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Functional test that sandbox SPI flash works correctly */
static int dm_test_spi_flash_func(struct unit_test_state *uts)
{
/*
* Create an empty test file and run the SPI flash tests. This is a
@ -39,4 +90,4 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

View file

@ -13,7 +13,7 @@ def in_tree(response, name, uclass, drv, depth, last_child):
else:
leaf = leaf + '`'
leaf = leaf + '-- ' + name
line = ' *{:10.10} [0-9]* \[ [ +] \] {:10.10} {}$'.format(uclass, drv,leaf)
line = ' *{:10.10} [0-9]* \[ [ +] \] {:20.20} {}$'.format(uclass, drv, leaf)
prog = re.compile(line)
for l in lines:
if prog.match(l):
@ -28,31 +28,31 @@ def test_bind_unbind_with_node(u_boot_console):
response = u_boot_console.run_command("bind /bind-test generic_simple_bus")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
#Unbind child #1. No error expected and all devices should be there except for bind-test-child1
response = u_boot_console.run_command("unbind /bind-test/bind-test-child1")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert "bind-test-child1" not in tree
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
#bind child #1. No error expected and all devices should be there
response = u_boot_console.run_command("bind /bind-test/bind-test-child1 phy_sandbox")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, False)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, False)
#Unbind child #2. No error expected and all devices should be there except for bind-test-child2
response = u_boot_console.run_command("unbind /bind-test/bind-test-child2")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
assert "bind-test-child2" not in tree
@ -61,9 +61,9 @@ def test_bind_unbind_with_node(u_boot_console):
response = u_boot_console.run_command("bind /bind-test/bind-test-child2 generic_simple_bus")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
#Unbind parent. No error expected. All devices should be removed and unbound
response = u_boot_console.run_command("unbind /bind-test")
@ -89,9 +89,9 @@ def test_bind_unbind_with_node(u_boot_console):
response = u_boot_console.run_command("bind /bind-test generic_simple_bus")
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
response = u_boot_console.run_command("unbind /bind-test")
assert response == ''
@ -138,7 +138,7 @@ def test_bind_unbind_with_uclass(u_boot_console):
response = u_boot_console.run_command("unbind simple_bus {}".format(child_of_child2_index))
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
assert not in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
child_of_child2_line = get_next_line(tree, "bind-test-child2")
assert child_of_child2_line == ""
@ -161,7 +161,7 @@ def test_bind_unbind_with_uclass(u_boot_console):
assert response == ''
tree = u_boot_console.run_command("dm tree")
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
child_of_child2_line = get_next_line(tree, "bind-test-child2")
assert child_of_child2_line == ""

View file

@ -723,6 +723,12 @@ If you need to specify a particular device-tree compiler to use, you can define
the DTC environment variable. This can be useful when the system dtc is too
old.
To enable a full backtrace and other debugging features in binman, pass
BINMAN_DEBUG=1 to your build:
make sandbox_defconfig
make BINMAN_DEBUG=1
History / Credits
-----------------

View file

@ -60,7 +60,7 @@ class Entry_blob(Entry):
except AttributeError:
data = lz4.compress(data)
'''
data = tools.Run('lz4', '-c', self._pathname, )
data = tools.Run('lz4', '-c', self._pathname)
self.SetContents(data)
return True

View file

@ -30,9 +30,8 @@ class Entry_u_boot_elf(Entry_blob):
out_fname = tools.GetOutputFilename('%s.stripped' % uniq)
tools.WriteFile(out_fname, tools.ReadFile(self._pathname))
tools.Run('strip', out_fname)
self.SetContents(tools.ReadFile(out_fname))
else:
self.SetContents(tools.ReadFile(self._pathname))
self._pathname = out_fname
Entry_blob.ReadBlobContents(self)
return True
def GetDefaultFilename(self):

View file

@ -290,6 +290,7 @@ class Builder:
self._re_function = re.compile('(.*): In function.*')
self._re_files = re.compile('In file included from.*')
self._re_warning = re.compile('(.*):(\d*):(\d*): warning: .*')
self._re_dtb_warning = re.compile('(.*): Warning .*')
self._re_note = re.compile('(.*):(\d*):(\d*): note: this is the location of the previous.*')
self.queue = Queue.Queue()
@ -788,7 +789,8 @@ class Builder:
self._re_files.match(line)):
last_func = line
else:
is_warning = self._re_warning.match(line)
is_warning = (self._re_warning.match(line) or
self._re_dtb_warning.match(line))
is_note = self._re_note.match(line)
if is_warning or (last_was_warning and is_note):
if last_func:
@ -1194,10 +1196,11 @@ class Builder:
Print(' ' + line, newline=True, colour=col)
better = [] # List of boards fixed since last commit
worse = [] # List of new broken boards since last commit
new = [] # List of boards that didn't exist last time
unknown = [] # List of boards that were not built
ok_boards = [] # List of boards fixed since last commit
warn_boards = [] # List of boards with warnings since last commit
err_boards = [] # List of new broken boards since last commit
new_boards = [] # List of boards that didn't exist last time
unknown_boards = [] # List of boards that were not built
for target in board_dict:
if target not in board_selected:
@ -1208,13 +1211,19 @@ class Builder:
base_outcome = self._base_board_dict[target].rc
outcome = board_dict[target]
if outcome.rc == OUTCOME_UNKNOWN:
unknown.append(target)
unknown_boards.append(target)
elif outcome.rc < base_outcome:
better.append(target)
if outcome.rc == OUTCOME_WARNING:
warn_boards.append(target)
else:
ok_boards.append(target)
elif outcome.rc > base_outcome:
worse.append(target)
if outcome.rc == OUTCOME_WARNING:
warn_boards.append(target)
else:
err_boards.append(target)
else:
new.append(target)
new_boards.append(target)
# Get a list of errors that have appeared, and disappeared
better_err, worse_err = _CalcErrorDelta(self._base_err_lines,
@ -1223,16 +1232,18 @@ class Builder:
self._base_warn_line_boards, warn_lines, warn_line_boards, 'w')
# Display results by arch
if (better or worse or unknown or new or worse_err or better_err
or worse_warn or better_warn):
if any((ok_boards, warn_boards, err_boards, unknown_boards, new_boards,
worse_err, better_err, worse_warn, better_warn)):
arch_list = {}
self.AddOutcome(board_selected, arch_list, better, '',
self.AddOutcome(board_selected, arch_list, ok_boards, '',
self.col.GREEN)
self.AddOutcome(board_selected, arch_list, worse, '+',
self.AddOutcome(board_selected, arch_list, warn_boards, 'w+',
self.col.YELLOW)
self.AddOutcome(board_selected, arch_list, err_boards, '+',
self.col.RED)
self.AddOutcome(board_selected, arch_list, new, '*', self.col.BLUE)
self.AddOutcome(board_selected, arch_list, new_boards, '*', self.col.BLUE)
if self._show_unknown:
self.AddOutcome(board_selected, arch_list, unknown, '?',
self.AddOutcome(board_selected, arch_list, unknown_boards, '?',
self.col.MAGENTA)
for arch, target_list in arch_list.iteritems():
Print('%10s: %s' % (arch, target_list))

View file

@ -66,7 +66,7 @@ def ParseArgs():
parser.add_option('-l', '--list-error-boards', action='store_true',
default=False, help='Show a list of boards next to each error/warning')
parser.add_option('--list-tool-chains', action='store_true', default=False,
help='List available tool chains')
help='List available tool chains (use -v to see probing detail)')
parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run',
default=False, help="Do a dry run (describe actions, but do nothing)")
parser.add_option('-N', '--no-subdirs', action='store_true', dest='no_subdirs',

View file

@ -164,7 +164,7 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
if no_toolchains:
toolchains.GetSettings()
toolchains.Scan(options.list_tool_chains)
toolchains.Scan(options.list_tool_chains and options.verbose)
if options.list_tool_chains:
toolchains.List()
print

View file

@ -46,8 +46,9 @@ make[1]: *** [main.o] Error 1
make: *** [common/libcommon.o] Error 2
Make failed
''',
'''main.c: In function 'main_loop3':
main.c:280:6: warning: unused variable 'mary' [-Wunused-variable]
'''arch/arm/dts/socfpga_arria10_socdk_sdmmc.dtb: Warning \
(avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells \
without "ranges" or child "reg" property
''',
'''powerpc-linux-ld: warning: dot moved backwards before `.bss'
powerpc-linux-ld: warning: dot moved backwards before `.bss'
@ -96,6 +97,8 @@ boards = [
BASE_DIR = 'base'
OUTCOME_OK, OUTCOME_WARN, OUTCOME_ERR = range(3)
class Options:
"""Class that holds build options"""
pass
@ -165,9 +168,10 @@ class TestBuild(unittest.TestCase):
result.combined = result.stdout + result.stderr
return result
def assertSummary(self, text, arch, plus, boards, ok=False):
def assertSummary(self, text, arch, plus, boards, outcome=OUTCOME_ERR):
col = self._col
expected_colour = col.GREEN if ok else col.RED
expected_colour = (col.GREEN if outcome == OUTCOME_OK else
col.YELLOW if outcome == OUTCOME_WARN else col.RED)
expect = '%10s: ' % arch
# TODO(sjg@chromium.org): If plus is '', we shouldn't need this
expect += ' ' + col.Color(expected_colour, plus)
@ -191,6 +195,8 @@ class TestBuild(unittest.TestCase):
build.do_make = self.Make
board_selected = self.boards.GetSelectedDict()
# Build the boards for the pre-defined commits and warnings/errors
# associated with each. This calls our Make() to inject the fake output.
build.BuildBoards(self.commits, board_selected, keep_outputs=False,
verbose=False)
lines = terminal.GetPrintTestLines()
@ -206,33 +212,49 @@ class TestBuild(unittest.TestCase):
build.ShowSummary(self.commits, board_selected)
#terminal.EchoPrintTestLines()
lines = terminal.GetPrintTestLines()
# Upstream commit: no errors
self.assertEqual(lines[0].text, '01: %s' % commits[0][1])
# Second commit: all archs should fail with warnings
self.assertEqual(lines[1].text, '02: %s' % commits[1][1])
# We expect all archs to fail
col = terminal.Color()
self.assertSummary(lines[2].text, 'sandbox', '+', ['board4'])
self.assertSummary(lines[3].text, 'arm', '+', ['board1'])
self.assertSummary(lines[4].text, 'powerpc', '+', ['board2', 'board3'])
self.assertSummary(lines[2].text, 'sandbox', 'w+', ['board4'],
outcome=OUTCOME_WARN)
self.assertSummary(lines[3].text, 'arm', 'w+', ['board1'],
outcome=OUTCOME_WARN)
self.assertSummary(lines[4].text, 'powerpc', 'w+', ['board2', 'board3'],
outcome=OUTCOME_WARN)
# Now we should have the compiler warning
# Second commit: The warnings should be listed
self.assertEqual(lines[5].text, 'w+%s' %
errors[0].rstrip().replace('\n', '\nw+'))
self.assertEqual(lines[5].colour, col.MAGENTA)
# Third commit: Still fails
self.assertEqual(lines[6].text, '03: %s' % commits[2][1])
self.assertSummary(lines[7].text, 'sandbox', '+', ['board4'])
self.assertSummary(lines[8].text, 'arm', '', ['board1'], ok=True)
self.assertSummary(lines[8].text, 'arm', '', ['board1'],
outcome=OUTCOME_OK)
self.assertSummary(lines[9].text, 'powerpc', '+', ['board2', 'board3'])
# Compiler error
# Expect a compiler error
self.assertEqual(lines[10].text, '+%s' %
errors[1].rstrip().replace('\n', '\n+'))
# Fourth commit: Compile errors are fixed, just have warning for board3
self.assertEqual(lines[11].text, '04: %s' % commits[3][1])
self.assertSummary(lines[12].text, 'sandbox', '', ['board4'], ok=True)
self.assertSummary(lines[13].text, 'powerpc', '', ['board2', 'board3'],
ok=True)
self.assertSummary(lines[12].text, 'sandbox', 'w+', ['board4'],
outcome=OUTCOME_WARN)
expect = '%10s: ' % 'powerpc'
expect += ' ' + col.Color(col.GREEN, '')
expect += ' '
expect += col.Color(col.GREEN, ' %s' % 'board2')
expect += ' ' + col.Color(col.YELLOW, 'w+')
expect += ' '
expect += col.Color(col.YELLOW, ' %s' % 'board3')
self.assertEqual(lines[13].text, expect)
# Compile error fixed
self.assertEqual(lines[14].text, '-%s' %
@ -243,9 +265,11 @@ class TestBuild(unittest.TestCase):
errors[2].rstrip().replace('\n', '\nw+'))
self.assertEqual(lines[15].colour, col.MAGENTA)
# Fifth commit
self.assertEqual(lines[16].text, '05: %s' % commits[4][1])
self.assertSummary(lines[17].text, 'sandbox', '+', ['board4'])
self.assertSummary(lines[18].text, 'powerpc', '', ['board3'], ok=True)
self.assertSummary(lines[18].text, 'powerpc', '', ['board3'],
outcome=OUTCOME_OK)
# The second line of errors[3] is a duplicate, so buildman will drop it
expect = errors[3].rstrip().split('\n')
@ -256,8 +280,10 @@ class TestBuild(unittest.TestCase):
self.assertEqual(lines[20].text, 'w-%s' %
errors[2].rstrip().replace('\n', '\nw-'))
# Sixth commit
self.assertEqual(lines[21].text, '06: %s' % commits[5][1])
self.assertSummary(lines[22].text, 'sandbox', '', ['board4'], ok=True)
self.assertSummary(lines[22].text, 'sandbox', '', ['board4'],
outcome=OUTCOME_OK)
# The second line of errors[3] is a duplicate, so buildman will drop it
expect = errors[3].rstrip().split('\n')
@ -268,6 +294,7 @@ class TestBuild(unittest.TestCase):
self.assertEqual(lines[24].text, 'w-%s' %
errors[0].rstrip().replace('\n', '\nw-'))
# Seventh commit
self.assertEqual(lines[25].text, '07: %s' % commits[6][1])
self.assertSummary(lines[26].text, 'sandbox', '+', ['board4'])