From gerrit at coreboot.org Tue Jan 1 03:03:59 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:03:59 +0100 Subject: [coreboot] New patch to review for coreboot: dcaec83 cleanup some exynos5250 uart code References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2084 -gerrit commit dcaec8388e9f4a4f0bcedfd34a19e4f91fc1ecda Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks --- src/cpu/samsung/exynos5250/uart.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..9f4f7f3 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -21,14 +21,8 @@ * */ -//#include -//#include #include #include -//#include -//#include -//#include -//#include #include /* for __console definition */ @@ -180,8 +174,6 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -/* FIXME: ordering of arguments for coreboot v. u-boot for tx_byte */ -//static void exynos5_tx_byte(const char c, const int dev_index) static void exynos5_uart_tx_byte(unsigned char data) { // struct s5p_uart *const uart = s5p_get_base_uart(dev_index); @@ -198,14 +190,6 @@ static void exynos5_uart_tx_byte(unsigned char data) #ifndef __PRE_RAM__ static const struct console_driver exynos5_uart_console __console = { -//static const struct console_driver exynos5_uart_console __console = { -#if 0 - void (*init)(void); - void (*tx_byte)(unsigned char byte); - void (*tx_flush)(void); - unsigned char (*rx_byte)(void); - int (*tst_byte)(void); -#endif .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, // .tx_flush = exynos5_uart_tx_flush, @@ -213,11 +197,6 @@ static const struct console_driver exynos5_uart_console __console = { // .tst_byte = exynos5_uart_tst_byte, }; #else -/* for romstage_console... */ -//void (*uart_init)(void) = exynos5_init_dev; -//unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; -//void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; -/* FIXME: trivial wrappers */ void uart_init() { exynos5_init_dev(); From gerrit at coreboot.org Tue Jan 1 03:03:59 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:03:59 +0100 Subject: [coreboot] New patch to review for coreboot: 668a858 enable early serial console on exynos5250 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2085 -gerrit commit 668a85883fdbebfdde633604cc91c1c6da6287e4 Author: David Hendricks Date: Mon Dec 31 17:55:29 2012 -0800 enable early serial console on exynos5250 Change-Id: Ib16308c72b86860e80caec96202c42991a7b1d1a Signed-off-by: David Hendricks --- src/cpu/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 4a09ca3..abfc049 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 select CPU_SAMSUNG_EXYNOS + select EARLY_SERIAL_CONSOLE bool default n From gerrit at coreboot.org Tue Jan 1 03:04:00 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:04:00 +0100 Subject: [coreboot] New patch to review for coreboot: 1aa888f make early serial console support more generic References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 1aa888fc93609f96cb19afd1a88085471489840b Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H From gerrit at coreboot.org Tue Jan 1 03:06:14 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:06:14 +0100 Subject: [coreboot] Patch set updated for coreboot: 50d7ef8 make early serial console support more generic References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 50d7ef8df779e9a4cd41d11bcc772518615918a9 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H From gerrit at coreboot.org Tue Jan 1 03:06:14 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:06:14 +0100 Subject: [coreboot] Patch set updated for coreboot: 8362128 cleanup some exynos5250 uart code References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2084 -gerrit commit 836212854884b85115df1eb8b69ac62656720a81 Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks --- src/cpu/samsung/exynos5250/uart.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..9f4f7f3 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -21,14 +21,8 @@ * */ -//#include -//#include #include #include -//#include -//#include -//#include -//#include #include /* for __console definition */ @@ -180,8 +174,6 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -/* FIXME: ordering of arguments for coreboot v. u-boot for tx_byte */ -//static void exynos5_tx_byte(const char c, const int dev_index) static void exynos5_uart_tx_byte(unsigned char data) { // struct s5p_uart *const uart = s5p_get_base_uart(dev_index); @@ -198,14 +190,6 @@ static void exynos5_uart_tx_byte(unsigned char data) #ifndef __PRE_RAM__ static const struct console_driver exynos5_uart_console __console = { -//static const struct console_driver exynos5_uart_console __console = { -#if 0 - void (*init)(void); - void (*tx_byte)(unsigned char byte); - void (*tx_flush)(void); - unsigned char (*rx_byte)(void); - int (*tst_byte)(void); -#endif .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, // .tx_flush = exynos5_uart_tx_flush, @@ -213,11 +197,6 @@ static const struct console_driver exynos5_uart_console __console = { // .tst_byte = exynos5_uart_tst_byte, }; #else -/* for romstage_console... */ -//void (*uart_init)(void) = exynos5_init_dev; -//unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; -//void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; -/* FIXME: trivial wrappers */ void uart_init() { exynos5_init_dev(); From gerrit at coreboot.org Tue Jan 1 03:06:15 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Tue, 1 Jan 2013 03:06:15 +0100 Subject: [coreboot] Patch set updated for coreboot: 5b294a4 enable early serial console on exynos5250 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2085 -gerrit commit 5b294a4267eeb2fe9a45520ce2cad574511e4591 Author: David Hendricks Date: Mon Dec 31 17:55:29 2012 -0800 enable early serial console on exynos5250 Change-Id: Ib16308c72b86860e80caec96202c42991a7b1d1a Signed-off-by: David Hendricks --- src/cpu/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 4a09ca3..abfc049 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 select CPU_SAMSUNG_EXYNOS + select EARLY_SERIAL_CONSOLE bool default n From ajg4tadpole at gmail.com Wed Jan 2 18:58:27 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Wed, 02 Jan 2013 17:58:27 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> Message-ID: <50E47543.8050102@gmail.com> On 02/01/13 17:08, ron minnich wrote: > On Mon, Dec 31, 2012 at 11:23 AM, David Hubbard > wrote: > >> Andrew has good points. Technically there's nothing about Secure Boot that >> can be proven to exclude alternative OS's such as Linux. > > While that is technically true, I am starting to see reports of > systems that, at the very least, are making it hard to boot anything > but Windows. Also. Microsoft has exercised its power to limit the > types of binaries that will be signed, e.g. anything built with GPL V3 > will not be signed. Now, while they may have valid reasons, this does > demonstrate the extent of Microsoft's power over platforms with Secure > Boot. I find it worrisome. Hmm the GPL v3 thing is indeed troublesome. However shim is being signed which does at least give us one way to boot GNU/Linux without turning Secure Boot off. You can then of course use GPL v3 code in the bootpath after shim. > Given what a mess the vendors have made of $PIR/_MP/ACPI over the > years, I don't see the UEFI Secure Boot situation being much better. > So, get ready for desktops/laptops that "should" boot non-Windows > OSes, but don't. I am sure that it is the old story, most testing will be done against Windows. Anything more will be the exception. This is where the pressure needs to be put on the platform vendors as this is the part that they are responsible for. When you find motherboards that will only boot Windows then make a noise about it, complain and send them back. When you find motherboards that work correctly then also make a noise but do it complimenting the vendor. > Garret's blog is well worth reading on this whole issue. Yes. > ron > Andrew From rminnich at gmail.com Wed Jan 2 19:04:14 2013 From: rminnich at gmail.com (ron minnich) Date: Wed, 2 Jan 2013 10:04:14 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E47543.8050102@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: On Wed, Jan 2, 2013 at 9:58 AM, Andrew Goodbody wrote: > I am sure that it is the old story, most testing will be done against > Windows. Anything more will be the exception. This is where the pressure > needs to be put on the platform vendors as this is the part that they are > responsible for. Sorry, vendors don't have a pattern of paying attention to end user sales issues such as "won't boot Linux". They are selling into a market in which Linux is about 1% at best of sales. That's been the common experience anyway, even at very large companies: BIOS issues just don't get fixed. ron From gerrit at coreboot.org Wed Jan 2 20:19:09 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Wed, 2 Jan 2013 20:19:09 +0100 Subject: [coreboot] Patch merged into coreboot/master: c855dce Supermicro H8QGI: Pass callout pointer to AmdReadEventLog function References: Message-ID: the following patch was just integrated into master: commit c855dce8250b6c1820f682fb4a009d37e6d59826 Author: Aladyshev Konstantin Date: Wed Dec 19 05:53:53 2012 +0400 Supermicro H8QGI: Pass callout pointer to AmdReadEventLog function I have issues when AmdReadEventLog function tries to use BiosCallouts interface. So it is necessary to provide callout pointer to this function. Change-Id: I4080e5f07d5d28c41688b2a7deff944b7a0f7bf7 Signed-off-by: Aladyshev Konstantin Reviewed-on: http://review.coreboot.org/2064 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones Reviewed-by: Zheng Bao Build-Tested: build bot (Jenkins) at Thu Dec 20 18:45:03 2012, giving +1 Reviewed-By: Marc Jones at Fri Dec 28 21:20:53 2012, giving +2 See http://review.coreboot.org/2064 for details. -gerrit From gerrit at coreboot.org Wed Jan 2 20:24:02 2013 From: gerrit at coreboot.org (Marc Jones (marcj303@gmail.com)) Date: Wed, 2 Jan 2013 20:24:02 +0100 Subject: [coreboot] Patch set updated for coreboot: e0d9046 AGESA: Use `Flag=AGESA_SUCCESS` instead of `TRUE` in DMI related functions References: Message-ID: Marc Jones (marcj303 at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2070 -gerrit commit e0d9046b9f22271480bd267dc01d4310664d2f79 Author: Aladyshev Konstantin Date: Wed Dec 19 09:31:01 2012 +0400 AGESA: Use `Flag=AGESA_SUCCESS` instead of `TRUE` in DMI related functions Success return value in DMI functions GetDmiInfoMain(..) and GetType4Type7Info(...) of AGESA vendorcode is "Flag = TRUE". This results in a failure of init late function: "agesawrapper_amdinitlate failed: 1" It happens because TRUE = 1 = AGESA_UNSUPPORTED. Replacing TRUE with AGESA_SUCCESS (= 0) fixes this problem. Only family f15tn does not have such bug. This patch just replaces TRUE with AGESA_SUCCESS, but maybe all DMI functions should be copied from Trinity family? Tested on Supermicro H8QGI board with 4 AMD Opteron 6234 processors (f15). Change-Id: I51bf91333c088a825b92d4a44d1ebe4380c8026c Signed-off-by: Aladyshev Konstantin Signed-off-by: Paul Menzel --- src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuDmi.c | 4 ++-- src/vendorcode/amd/agesa/f12/Proc/CPU/Feature/cpuDmi.c | 4 ++-- src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuDmi.c | 4 ++-- src/vendorcode/amd/agesa/f15/Proc/CPU/Feature/cpuDmi.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuDmi.c b/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuDmi.c index 9e7ea86..2496779 100644 --- a/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuDmi.c +++ b/src/vendorcode/amd/agesa/f10/Proc/CPU/Feature/cpuDmi.c @@ -206,7 +206,7 @@ GetDmiInfoMain ( LOCATE_HEAP_PTR LocateHeapParams; MsrData = 0; - Flag = TRUE; + Flag = AGESA_SUCCESS; DmiBufferPtr = *DmiTable; if (DmiBufferPtr == NULL) { // @@ -387,7 +387,7 @@ GetType4Type7Info ( PROC_FAMILY_TABLE *ProcData; CPU_LOGICAL_ID LogicalID; - Flag = TRUE; + Flag = AGESA_SUCCESS; DmiBufferPtr = (DMI_INFO *) ApExeParams->RelatedDataBlock; GetLogicalIdOfCurrentCore (&LogicalID, &ApExeParams->StdHeader); diff --git a/src/vendorcode/amd/agesa/f12/Proc/CPU/Feature/cpuDmi.c b/src/vendorcode/amd/agesa/f12/Proc/CPU/Feature/cpuDmi.c index 60095d0..999ccf5 100644 --- a/src/vendorcode/amd/agesa/f12/Proc/CPU/Feature/cpuDmi.c +++ b/src/vendorcode/amd/agesa/f12/Proc/CPU/Feature/cpuDmi.c @@ -216,7 +216,7 @@ GetDmiInfoMain ( CPU_GET_MEM_INFO CpuGetMemInfo; MsrData = 0; - Flag = TRUE; + Flag = AGESA_SUCCESS; ProcData = NULL; MemInfo = NULL; DmiBufferPtr = *DmiTable; @@ -415,7 +415,7 @@ GetType4Type7Info ( PROC_FAMILY_TABLE *ProcData; CPU_LOGICAL_ID LogicalID; - Flag = TRUE; + Flag = AGESA_SUCCESS; DmiBufferPtr = (DMI_INFO *) ApExeParams->RelatedDataBlock; GetLogicalIdOfCurrentCore (&LogicalID, &ApExeParams->StdHeader); diff --git a/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuDmi.c b/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuDmi.c index 0bf357d..b816732 100644 --- a/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuDmi.c +++ b/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuDmi.c @@ -220,7 +220,7 @@ GetDmiInfoMain ( CPU_GET_MEM_INFO CpuGetMemInfo; MsrData = 0; - Flag = TRUE; + Flag = AGESA_SUCCESS; ProcData = NULL; MemInfo = NULL; DmiBufferPtr = *DmiTable; @@ -429,7 +429,7 @@ GetType4Type7Info ( PROC_FAMILY_TABLE *ProcData; CPU_LOGICAL_ID LogicalID; - Flag = TRUE; + Flag = AGESA_SUCCESS; DmiBufferPtr = (DMI_INFO *) ApExeParams->RelatedDataBlock; GetLogicalIdOfCurrentCore (&LogicalID, &ApExeParams->StdHeader); diff --git a/src/vendorcode/amd/agesa/f15/Proc/CPU/Feature/cpuDmi.c b/src/vendorcode/amd/agesa/f15/Proc/CPU/Feature/cpuDmi.c index 5619df3..2385752 100644 --- a/src/vendorcode/amd/agesa/f15/Proc/CPU/Feature/cpuDmi.c +++ b/src/vendorcode/amd/agesa/f15/Proc/CPU/Feature/cpuDmi.c @@ -219,7 +219,7 @@ GetDmiInfoMain ( CPU_GET_MEM_INFO CpuGetMemInfo; MsrData = 0; - Flag = TRUE; + Flag = AGESA_SUCCESS; ProcData = NULL; MemInfo = NULL; DmiBufferPtr = *DmiTable; @@ -439,7 +439,7 @@ GetType4Type7Info ( CPU_LOGICAL_ID LogicalID; UINT8 L3Associativity; - Flag = TRUE; + Flag = AGESA_SUCCESS; DmiBufferPtr = (DMI_INFO *) ApExeParams->RelatedDataBlock; GetLogicalIdOfCurrentCore (&LogicalID, &ApExeParams->StdHeader); From paulepanter at users.sourceforge.net Wed Jan 2 20:27:28 2013 From: paulepanter at users.sourceforge.net (Paul Menzel) Date: Wed, 02 Jan 2013 20:27:28 +0100 Subject: [coreboot] BIOS vendors and Linux testing (was: Feedback On Coreboot: the Solution to the Secure Boot Fiasco) In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: <1357154848.6199.3.camel@mattotaupa> Am Mittwoch, den 02.01.2013, 10:04 -0800 schrieb ron minnich: > On Wed, Jan 2, 2013 at 9:58 AM, Andrew Goodbody wrote: > > > I am sure that it is the old story, most testing will be done against > > Windows. Anything more will be the exception. This is where the pressure > > needs to be put on the platform vendors as this is the part that they are > > responsible for. > > Sorry, vendors don't have a pattern of paying attention to end user > sales issues such as "won't boot Linux". They are selling into a > market in which Linux is about 1% at best of sales. That's been the > common experience anyway, even at very large companies: BIOS issues > just don't get fixed. Well at least ASRock did test Ubuntu on one system and fixed it. This is in the changelog for BIOS version 1.70 for the ASRock E350M1 [1]. ?2. Modify Ubuntu 12.04 can not shutdown issue.? I guess either the coreboot porters told them, Canonical exercised pressure or one of the ASRock employees uses Ubuntu at home. ;-) Thanks, Paul [1] http://www.asrock.com/mb/overview.asp?cat=Download&os=BIOS&Model=E350M1 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: This is a digitally signed message part URL: From gerrit at coreboot.org Wed Jan 2 20:37:17 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Wed, 2 Jan 2013 20:37:17 +0100 Subject: [coreboot] Patch merged into coreboot/master: f50fbe8 AGESA: Use `Flag=AGESA_SUCCESS` instead of `TRUE` in DMI related functions References: Message-ID: the following patch was just integrated into master: commit f50fbe82ad0837ae7b30d7e2a5570ffc0dcc3950 Author: Aladyshev Konstantin Date: Wed Dec 19 09:31:01 2012 +0400 AGESA: Use `Flag=AGESA_SUCCESS` instead of `TRUE` in DMI related functions Success return value in DMI functions GetDmiInfoMain(..) and GetType4Type7Info(...) of AGESA vendorcode is "Flag = TRUE". This results in a failure of init late function: "agesawrapper_amdinitlate failed: 1" It happens because TRUE = 1 = AGESA_UNSUPPORTED. Replacing TRUE with AGESA_SUCCESS (= 0) fixes this problem. Only family f15tn does not have such bug. This patch just replaces TRUE with AGESA_SUCCESS, but maybe all DMI functions should be copied from Trinity family? Tested on Supermicro H8QGI board with 4 AMD Opteron 6234 processors (f15). Change-Id: I51bf91333c088a825b92d4a44d1ebe4380c8026c Signed-off-by: Aladyshev Konstantin Signed-off-by: Paul Menzel Reviewed-on: http://review.coreboot.org/2070 Reviewed-by: Marc Jones Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Wed Jan 2 20:35:22 2013, giving +1 Reviewed-By: Marc Jones at Wed Jan 2 20:26:02 2013, giving +2 See http://review.coreboot.org/2070 for details. -gerrit From david.c.hubbard+coreboot at gmail.com Wed Jan 2 20:28:36 2013 From: david.c.hubbard+coreboot at gmail.com (David Hubbard) Date: Wed, 2 Jan 2013 12:28:36 -0700 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: On Wed, Jan 2, 2013 at 11:04 AM, ron minnich wrote: > On Wed, Jan 2, 2013 at 9:58 AM, Andrew Goodbody > wrote: > > > I am sure that it is the old story, most testing will be done against > > Windows. Anything more will be the exception. This is where the pressure > > needs to be put on the platform vendors as this is the part that they are > > responsible for. > > Sorry, vendors don't have a pattern of paying attention to end user > sales issues such as "won't boot Linux". They are selling into a > market in which Linux is about 1% at best of sales. That's been the > common experience anyway, even at very large companies: BIOS issues > just don't get fixed. > > Andrew, Ron, what's your take on http://mjg59.dreamwidth.org/20916.html ? Specifically: "This is part of Windows 8's fast boot support - the keyboard may not be initialised until after the OS has started." So the logic goes: 1. Secure Boot enabled and Win8 installed by the OEM 2. To access the BIOS, press F2/F8/DEL/whatever 3. "Fast boot" (hey! coreboot delivered on that first!) skips keyboard init 4. User is thus *forced* to use Win8's "hold down shift and restart" feature -- adding another barrier before a user can boot her own OS. I think the biggest problem here is that the entire BIOS is made inaccessible, and only if Windows gives permission can you change that. Regards, David -------------- next part -------------- An HTML attachment was scrubbed... URL: From r.marek at assembler.cz Wed Jan 2 22:43:58 2013 From: r.marek at assembler.cz (Rudolf Marek) Date: Wed, 02 Jan 2013 22:43:58 +0100 Subject: [coreboot] FOSDEM 2013 - who else comes? Message-ID: <50E4AA1E.8030508@assembler.cz> Hi all, As Carl-Daniel wrote we have a stand (two tables) at FOSDEM on 2,3rd February in Brussel. So far me and Carl-Daniel will come. I will arrive early on Friday and leave on Sunday evening. I will bring my boards with me (2?) and of course also F2A85-M. If anyone wants to come, please let us know. Thanks Rudolf From gerrit at coreboot.org Wed Jan 2 23:15:15 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:15 +0100 Subject: [coreboot] Patch set updated for coreboot: 1c27787 armv7: create init.S for early ARMv7 init References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2083 -gerrit commit 1c27787a247123f6f966d7774c117c0899c089aa Author: David Hendricks Date: Thu Dec 27 15:23:57 2012 -0800 armv7: create init.S for early ARMv7 init The old start.S file did a lot of work and had AP-specific #ifndef's. The new init.S will eventually contain only bare minimum generic ARM code for use by the bootblock. Processor-specific stuff and things that take place later in the boot process should go elsewhere. Change-Id: I7db0a77ee4bbad1ddecb193ea125d8941a50532b Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 4 +- src/arch/armv7/init/init.S | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index b413d3e..1a1271f 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -142,9 +142,7 @@ endif CFLAGS += -D__KERNEL__ CFLAGS += -D__LINUX_ARM_ARCH__=7 -# FIXME(dhendrix): trying to split start.S apart... -crt0s = $(src)/arch/armv7/start.S -#crt0s = $(src)/arch/armv7/romstage.S +crt0s = $(src)/arch/armv7/init/init.S ldscripts = ldscripts += $(src)/arch/armv7/romstage.ld diff --git a/src/arch/armv7/init/init.S b/src/arch/armv7/init/init.S new file mode 100644 index 0000000..033637e --- /dev/null +++ b/src/arch/armv7/init/init.S @@ -0,0 +1,94 @@ +/* + * Early initialization code for ARMv7 architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gr?ger + * Copyright (c) 2002 Alex Z?pke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define __ASSEMBLY__ +#include + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq +_undefined_instruction: .word _undefined_instruction +_software_interrupt: .word _software_interrupt +_prefetch_abort: .word _prefetch_abort +_data_abort: .word _data_abort +_not_used: .word _not_used +_irq: .word _irq +_fiq: .word _fiq +_pad: .word 0x12345678 /* now 16*4=64 */ + + .balignl 16,0xdeadbeef + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr,r0 + + /* + * From Cortex-A Series Programmer's Guide: + * Only CPU 0 performs initialization. Other CPUs go into WFI + * to do this, first work out which CPU this is + * this code typically is run before any other initialization step + */ + mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register + and r1, r1, #0x3 @ Extract CPU ID bits + cmp r1, #0 + bne wait_for_interrupt @ If this is not core0, wait + + /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ + mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register + bic r0, #CR_V @ V = 0 + mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register + + /* Set vector address in CP15 VBAR register */ + ldr r0, =_start + mcr p15, 0, r0, c12, c0, 0 @Set VBAR + +/* Set stackpointer in internal RAM to call board_init_f */ +call_board_init_f: + ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) + mov sp, r0 + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr r0,=0x00000000 + bl board_init_f + +wait_for_interrupt: + wfi + mov pc, lr @ back to my caller From gerrit at coreboot.org Wed Jan 2 23:15:15 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:15 +0100 Subject: [coreboot] Patch set updated for coreboot: fea3790 import SPL files for board_i2c_{claim, release}_bus() References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2081 -gerrit commit fea3790fda51a57c2e7c047232f445ce6c9d8c82 Author: David Hendricks Date: Thu Dec 27 15:11:27 2012 -0800 import SPL files for board_i2c_{claim,release}_bus() This imports SPL (second phase loader) files from U-Boot. Most of the content of these files will eventually go away since they're fairly U-Boot specific. For now they are here to make Jenkins happy. Change-Id: Ib3a365ecb9dc304b20f7c1c06665aad2c0c53e69 Signed-off-by: David Hendricks --- src/cpu/samsung/exynos5-common/spl.h | 4 ++++ src/mainboard/google/snow/smdk5250_spl.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/cpu/samsung/exynos5-common/spl.h b/src/cpu/samsung/exynos5-common/spl.h index afa9a8e..439e1b0 100644 --- a/src/cpu/samsung/exynos5-common/spl.h +++ b/src/cpu/samsung/exynos5-common/spl.h @@ -91,4 +91,8 @@ struct spl_machine_param *spl_get_machine_params(void); */ void spl_early_init(void); +/* FIXME(dhendrix): for early i2c init */ +void board_i2c_release_bus(int node); +int board_i2c_claim_bus(int node); + #endif /* __ASM_ARCH_EXYNOS_SPL_H__ */ diff --git a/src/mainboard/google/snow/smdk5250_spl.c b/src/mainboard/google/snow/smdk5250_spl.c index 204e411..0dbd4e1 100644 --- a/src/mainboard/google/snow/smdk5250_spl.c +++ b/src/mainboard/google/snow/smdk5250_spl.c @@ -24,8 +24,7 @@ #define SIGNATURE 0xdeadbeef /* Parameters of early board initialization in SPL */ -static struct spl_machine_param machine_param - __attribute__((section(".machine_param"))) = { +static struct spl_machine_param machine_param = { .signature = SIGNATURE, .version = 1, .params = "vmubfasirMw", @@ -65,6 +64,18 @@ struct spl_machine_param *spl_get_machine_params(void) return &machine_param; } +#if 0 +int board_get_revision(void) +{ + struct spl_machine_param *params = spl_get_machine_params(); + unsigned gpio[CONFIG_BOARD_REV_GPIO_COUNT]; + + gpio[0] = params->board_rev_gpios & 0xffff; + gpio[1] = params->board_rev_gpios >> 16; + return gpio_decode_number(gpio, CONFIG_BOARD_REV_GPIO_COUNT); +} +#endif + int board_wakeup_permitted(void) { struct spl_machine_param *param = spl_get_machine_params(); @@ -76,3 +87,18 @@ int board_wakeup_permitted(void) return !is_bad_wake; } + +/* + * TODO(sjg at chromium.org): + * Declared there here for SPL, since there is no core i2c subsystem and + * cmd_i2c.c is not included. + */ +void board_i2c_release_bus(int node) +{ +} + +int board_i2c_claim_bus(int node) +{ + /* EC is not allowed to touch the bus until we enter U-Boot */ + return 0; +} From gerrit at coreboot.org Wed Jan 2 23:15:15 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:15 +0100 Subject: [coreboot] Patch set updated for coreboot: 23c0bdd make early serial console support more generic References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 23c0bdd5bc9118401f510b2bee8fa38b6e4b6a46 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H From gerrit at coreboot.org Wed Jan 2 23:15:16 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:16 +0100 Subject: [coreboot] Patch set updated for coreboot: 71dcd75 cleanup some exynos5250 uart code References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2084 -gerrit commit 71dcd75fa9b7dee8efc4a07b4d8e8c1b62acf807 Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks --- src/cpu/samsung/exynos5250/uart.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..9f4f7f3 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -21,14 +21,8 @@ * */ -//#include -//#include #include #include -//#include -//#include -//#include -//#include #include /* for __console definition */ @@ -180,8 +174,6 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -/* FIXME: ordering of arguments for coreboot v. u-boot for tx_byte */ -//static void exynos5_tx_byte(const char c, const int dev_index) static void exynos5_uart_tx_byte(unsigned char data) { // struct s5p_uart *const uart = s5p_get_base_uart(dev_index); @@ -198,14 +190,6 @@ static void exynos5_uart_tx_byte(unsigned char data) #ifndef __PRE_RAM__ static const struct console_driver exynos5_uart_console __console = { -//static const struct console_driver exynos5_uart_console __console = { -#if 0 - void (*init)(void); - void (*tx_byte)(unsigned char byte); - void (*tx_flush)(void); - unsigned char (*rx_byte)(void); - int (*tst_byte)(void); -#endif .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, // .tx_flush = exynos5_uart_tx_flush, @@ -213,11 +197,6 @@ static const struct console_driver exynos5_uart_console __console = { // .tst_byte = exynos5_uart_tst_byte, }; #else -/* for romstage_console... */ -//void (*uart_init)(void) = exynos5_init_dev; -//unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; -//void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; -/* FIXME: trivial wrappers */ void uart_init() { exynos5_init_dev(); From gerrit at coreboot.org Wed Jan 2 23:15:16 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:16 +0100 Subject: [coreboot] Patch set updated for coreboot: 51e3674 enable early serial console on exynos5250 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2085 -gerrit commit 51e3674e977117da41e97c601ddc51dd528812aa Author: David Hendricks Date: Mon Dec 31 17:55:29 2012 -0800 enable early serial console on exynos5250 Change-Id: Ib16308c72b86860e80caec96202c42991a7b1d1a Signed-off-by: David Hendricks --- src/cpu/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 4a09ca3..abfc049 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 select CPU_SAMSUNG_EXYNOS + select EARLY_SERIAL_CONSOLE bool default n From gerrit at coreboot.org Wed Jan 2 23:15:17 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 2 Jan 2013 23:15:17 +0100 Subject: [coreboot] Patch set updated for coreboot: 16a5ddb Add (hacked-up) s3c24x0_i2c files References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2078 -gerrit commit 16a5ddbc14e03d87561712136d13341fdd33c357 Author: David Hendricks Date: Thu Dec 27 14:06:05 2012 -0800 Add (hacked-up) s3c24x0_i2c files These are needed for communicating with the PMIC on Snow. We'll tidy them up as we go along... Change-Id: I197f59927eae0ad66191862d052de2a8873fb22f Signed-off-by: David Hendricks --- src/cpu/samsung/s5p-common/Makefile.inc | 2 + src/cpu/samsung/s5p-common/s3c24x0_i2c.c | 640 +++++++++++++++++++++++++++++++ src/cpu/samsung/s5p-common/s3c24x0_i2c.h | 43 +++ 3 files changed, 685 insertions(+) diff --git a/src/cpu/samsung/s5p-common/Makefile.inc b/src/cpu/samsung/s5p-common/Makefile.inc index 9747f0d..7de3c28 100644 --- a/src/cpu/samsung/s5p-common/Makefile.inc +++ b/src/cpu/samsung/s5p-common/Makefile.inc @@ -2,6 +2,7 @@ romstage-y += cpu_info.c romstage-y += pwm.c # needed by timer.c romstage-y += s5p_gpio.c romstage-y += timer.c +romstage-y += s3c24x0_i2c.c #romstage-y += sromc.c #romstage-y += wdt.c @@ -10,3 +11,4 @@ ramstage-y += cpu_info.c ramstage-y += pwm.c # needed by timer.c ramstage-y += timer.c ramstage-y += s5p_gpio.c +ramstage-y += s3c24x0_i2c.c diff --git a/src/cpu/samsung/s5p-common/s3c24x0_i2c.c b/src/cpu/samsung/s5p-common/s3c24x0_i2c.c new file mode 100644 index 0000000..0b6f768 --- /dev/null +++ b/src/cpu/samsung/s5p-common/s3c24x0_i2c.c @@ -0,0 +1,640 @@ +/* + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller at elsoft.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same I2C controller inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include +#include +#include "clk.h" +#include "cpu/samsung/exynos5-common/clk.h" +#include "cpu/samsung/exynos5250/cpu.h" +#include "gpio.h" +#include "cpu/samsung/exynos5250/gpio.h" +#include "cpu/samsung/exynos5250/pinmux.h" + +//#include +#include "device/i2c.h" +#include "s3c24x0_i2c.h" + +/* for board_i2c_* */ +#include "cpu/samsung/exynos5-common/spl.h" + +#define I2C_WRITE 0 +#define I2C_READ 1 + +#define I2C_OK 0 +#define I2C_NOK 1 +#define I2C_NACK 2 +#define I2C_NOK_LA 3 /* Lost arbitration */ +#define I2C_NOK_TOUT 4 /* time out */ + +#define I2CSTAT_BSY 0x20 /* Busy bit */ +#define I2CSTAT_NACK 0x01 /* Nack bit */ +#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ +#define I2CCON_IRPND 0x10 /* Interrupt pending bit */ +#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ +#define I2C_MODE_MR 0x80 /* Master Receive Mode */ +#define I2C_START_STOP 0x20 /* START / STOP */ +#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ + +/* The timeouts we live by */ +enum { + I2C_XFER_TIMEOUT_MS = 35, /* xfer to complete */ + I2C_INIT_TIMEOUT_MS = 1000, /* bus free on init */ + I2C_IDLE_TIMEOUT_MS = 100, /* waiting for bus idle */ + I2C_STOP_TIMEOUT_US = 200, /* waiting for stop events */ +}; + +/* We should not rely on any particular ordering of these IDs */ +#if 0 +#ifndef CONFIG_OF_CONTROL +static enum periph_id periph_for_dev[EXYNOS_I2C_MAX_CONTROLLERS] = { + PERIPH_ID_I2C0, + PERIPH_ID_I2C1, + PERIPH_ID_I2C2, + PERIPH_ID_I2C3, + PERIPH_ID_I2C4, + PERIPH_ID_I2C5, + PERIPH_ID_I2C6, + PERIPH_ID_I2C7, +}; +#endif +#endif + +static unsigned int g_current_bus __attribute__((section(".data"))); +static struct s3c24x0_i2c *g_early_i2c_config __attribute__((section(".data"))); + +static struct s3c24x0_i2c_bus i2c_bus[EXYNOS_I2C_MAX_CONTROLLERS] + __attribute__((section(".data"))); +static int i2c_busses __attribute__((section(".data"))); + +void i2c_set_early_reg(unsigned int base) +{ + g_early_i2c_config = (struct s3c24x0_i2c *)base; +} + +static struct s3c24x0_i2c_bus *get_bus(int bus_idx) +{ + /* If an early i2c config exists we just use that */ + if (g_early_i2c_config) { + /* FIXME: value not retained from i2c_set_early_reg()? (but then, how + * did if (!i2c) check pass earlier on? Corrupt value? */ + i2c_bus[0].regs = g_early_i2c_config; + return &i2c_bus[0]; + } + + if (bus_idx < i2c_busses) + return &i2c_bus[bus_idx]; + debug("Undefined bus: %d\n", bus_idx); + return NULL; +} + +static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void) +{ + return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE); +} + +static int WaitForXfer(struct s3c24x0_i2c *i2c) +{ + int i; + + i = I2C_XFER_TIMEOUT_MS * 20; + while (!(readl(&i2c->iiccon) & I2CCON_IRPND)) { + if (i == 0) { + debug("%s: i2c xfer timeout\n", __func__); + return I2C_NOK_TOUT; + } + udelay(50); + i--; + } + + return I2C_OK; +} + +static int IsACK(struct s3c24x0_i2c *i2c) +{ + return !(readl(&i2c->iicstat) & I2CSTAT_NACK); +} + +static void ReadWriteByte(struct s3c24x0_i2c *i2c) +{ + uint32_t x; + + x = readl(&i2c->iiccon); + writel(x & ~I2CCON_IRPND, &i2c->iiccon); + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ +// writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); +} + +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) +{ + ulong freq, pres = 16, div; + + freq = clock_get_periph_rate(PERIPH_ID_I2C0); + /* calculate prescaler and divisor values */ + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + + while ((freq / pres / (div + 1)) > speed) + div++; + + /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ + writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); + + /* init to SLAVE REVEIVE and set slaveaddr */ + writel(0, &i2c->iicstat); + writel(slaveadd, &i2c->iicadd); + /* program Master Transmit (and implicit STOP) */ + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); +} + +/* TODO: determine if this is necessary to init board using FDT-provided info */ +#if 0 +void board_i2c_init(const void *blob) +{ + /* + * Turn off the early i2c configuration and init the i2c properly, + * this is done here to enable the use of i2c configs from FDT. + */ + i2c_set_early_reg(0); + +#ifdef CONFIG_OF_CONTROL + int node_list[EXYNOS_I2C_MAX_CONTROLLERS]; + int i, count; + + count = fdtdec_find_aliases_for_id(blob, "i2c", + COMPAT_SAMSUNG_S3C2440_I2C, node_list, + EXYNOS_I2C_MAX_CONTROLLERS); + + for (i = 0; i < count; i++) { + struct s3c24x0_i2c_bus *bus; + int node = node_list[i]; + + if (node < 0) + continue; + bus = &i2c_bus[i2c_busses]; + bus->regs = (struct s3c24x0_i2c *) + fdtdec_get_addr(blob, node, "reg"); + bus->id = (enum periph_id) + fdtdec_get_int(blob, node, "samsung,periph-id", -1); + bus->node = node; + bus->bus_num = i2c_busses++; + } +#else + int i; + + for (i = 0; i < EXYNOS_I2C_MAX_CONTROLLERS; i++) { + uintptr_t reg_addr = samsung_get_base_i2c() + + EXYNOS_I2C_SPACING * i; + + i2c_bus[i].regs = (struct s3c24x0_i2c_bus *)reg_addr; + i2c_bus[i].id = periph_for_dev[i]; + } + i2c_busses = EXYNOS_I2C_MAX_CONTROLLERS; +#endif +} +#endif + +/* + * MULTI BUS I2C support + */ +/* + * FIXME(dhendrix): not sure why this had to be guarded, but the code + * should probably go into an exynos5-specific .c file if it really is + * not generic. + */ +//#ifdef CONFIG_EXYNOS5 +static void i2c_bus_init(struct s3c24x0_i2c_bus *i2c, unsigned int bus) +{ + exynos_pinmux_config(i2c->id, 0); + + i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +} +//#else +//#error "should not be here" +//static void i2c_bus_init(struct s3c24x0_i2c_bus *i2c, unsigned int bus) {} +//#endif + +#ifdef CONFIG_I2C_MULTI_BUS +int i2c_set_bus_num(unsigned int bus) +{ + struct s3c24x0_i2c_bus *i2c; + + i2c = get_bus(bus); + if (!i2c) + return -1; + g_current_bus = bus; + i2c_bus_init(i2c, g_current_bus); + + return 0; +} + +unsigned int i2c_get_bus_num(void) +{ + return g_current_bus; +} +#endif + +#ifdef CONFIG_OF_CONTROL +int i2c_get_bus_num_fdt(const void *blob, int node) +{ + enum fdt_compat_id compat; + fdt_addr_t reg; + int i; + + compat = fdtdec_lookup(blob, node); + if (compat != COMPAT_SAMSUNG_S3C2440_I2C) { + debug("%s: Not a supported I2C node\n", __func__); + return -1; + } + + reg = fdtdec_get_addr(blob, node, "reg"); + for (i = 0; i < i2c_busses; i++) + if (reg == (fdt_addr_t)(uintptr_t)i2c_bus[i].regs) + return i; + + debug("%s: Can't find any matched I2C bus\n", __func__); + return -1; +} + +int i2c_reset_port_fdt(const void *blob, int node) +{ + struct s3c24x0_i2c_bus *i2c; + + int bus; + + bus = i2c_get_bus_num_fdt(blob, node); + if (bus < 0) { + printf("could not get bus for node %d\n", node); + return -1; + } + i2c = get_bus(bus); + if (!i2c) { + printf("get_bus() failed for node node %d\n", node); + return -1; + } + + i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + return 0; +} +#endif + +/* + * Verify the whether I2C ACK was received or not + * + * @param i2c pointer to I2C register base + * @param buf array of data + * @param len length of data + * return I2C_OK when transmission done + * I2C_NACK otherwise + */ +static int i2c_send_verify(struct s3c24x0_i2c *i2c, unsigned char buf[], + unsigned char len) +{ + int i, result = I2C_OK; + + if (IsACK(i2c)) { + for (i = 0; (i < len) && (result == I2C_OK); i++) { + writel(buf[i], &i2c->iicds); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + if (result == I2C_OK && !IsACK(i2c)) + result = I2C_NACK; + } + } else { + result = I2C_NACK; + } + + return result; +} + +void i2c_init(int speed, int slaveadd) +{ + struct s3c24x0_i2c_bus *i2c; + struct exynos5_gpio_part1 *gpio; + int i; + uint32_t x; + + /* By default i2c channel 0 is the current bus */ + g_current_bus = 0; + + i2c = get_bus(g_current_bus); + if (!i2c) + return; + + i2c_bus_init(i2c, g_current_bus); + + /* wait for some time to give previous transfer a chance to finish */ + i = I2C_INIT_TIMEOUT_MS * 20; + while ((readl(&i2c->regs->iicstat) & I2CSTAT_BSY) && (i > 0)) { + udelay(50); + i--; + } + + gpio = exynos_get_base_gpio1(); + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ +// writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con); + x = readl(&gpio->b3.con); + writel((x & ~0x00FF) | 0x0022, &gpio->b3.con); + + i2c_ch_init(i2c->regs, speed, slaveadd); +} + +/* + * Send a STOP event and wait for it to have completed + * + * @param mode If it is a master transmitter or receiver + * @return I2C_OK if the line became idle before timeout I2C_NOK_TOUT otherwise + */ +static int i2c_send_stop(struct s3c24x0_i2c *i2c, int mode) +{ + int timeout; + + /* Setting the STOP event to fire */ + writel(mode | I2C_TXRX_ENA, &i2c->iicstat); + ReadWriteByte(i2c); + + /* Wait for the STOP to send and the bus to go idle */ + for (timeout = I2C_STOP_TIMEOUT_US; timeout > 0; timeout -= 5) { + if (!(readl(&i2c->iicstat) & I2CSTAT_BSY)) + return I2C_OK; + udelay(5); + } + + return I2C_NOK_TOUT; +} + +/* + * cmd_type is 0 for write, 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + */ +static int i2c_transfer(struct s3c24x0_i2c *i2c, + unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], + unsigned short data_len) +{ + int i, result, stop_bit_result; + uint32_t x; + + if (data == 0 || data_len == 0) { + /* Don't support data transfer of no length or to address 0 */ + debug("i2c_transfer: bad call\n"); + return I2C_NOK; + } + + /* Check I2C bus idle */ + i = I2C_IDLE_TIMEOUT_MS * 20; + while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) { + udelay(50); + i--; + } + + if (readl(&i2c->iicstat) & I2CSTAT_BSY) { + debug("%s: bus busy\n", __func__); + return I2C_NOK_TOUT; + } + + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ + //writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); + x = readl(&i2c->iiccon); + writel(x | I2CCON_ACKGEN, &i2c->iiccon); + + if (addr && addr_len) { + writel(chip, &i2c->iicds); + /* send START */ + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, addr, addr_len); + else + result = I2C_NACK; + } else + result = I2C_NACK; + + switch (cmd_type) { + case I2C_WRITE: + if (result == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); + else { + writel(chip, &i2c->iicds); + /* send START */ + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); + } + + if (result == I2C_OK) + result = WaitForXfer(i2c); + + stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MT); + break; + + case I2C_READ: + { + int was_ok = (result == I2C_OK); + + writel(chip, &i2c->iicds); + /* resend START */ + writel(I2C_MODE_MR | I2C_TXRX_ENA | + I2C_START_STOP, &i2c->iicstat); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + + if (was_ok || IsACK(i2c)) { + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) { + /* FIXME(dhendrix): nested macro */ +#if 0 + writel(readl(&i2c->iiccon) & + ~I2CCON_ACKGEN, + &i2c->iiccon); +#endif + x = readl(&i2c->iiccon) & ~I2CCON_ACKGEN; + writel(x, &i2c->iiccon); + } + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + data[i] = readl(&i2c->iicds); + i++; + } + } else { + result = I2C_NACK; + } + + stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MR); + break; + } + + default: + debug("i2c_transfer: bad call\n"); + result = stop_bit_result = I2C_NOK; + break; + } + + /* + * If the transmission went fine, then only the stop bit was left to + * fail. Otherwise, the real failure we're interested in came before + * that, during the actual transmission. + */ + return (result == I2C_OK) ? stop_bit_result : result; +} + +int i2c_probe(uchar chip) +{ + struct s3c24x0_i2c_bus *i2c; + uchar buf[1]; + int ret; + + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + buf[0] = 0; + + /* + * What is needed is to send the chip address and verify that the + * address was ed (i.e. there was a chip at that address which + * drove the data line low). + */ + if (board_i2c_claim_bus(i2c->node)) { + debug("I2C cannot claim bus %d\n", i2c->bus_num); + return -1; + } + ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, 0, 0, buf, 1); + board_i2c_release_bus(i2c->node); + + return ret != I2C_OK; +} + +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + struct s3c24x0_i2c_bus *i2c; + uchar xaddr[4]; + int ret; + + if (alen > 4) { + debug("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + if (board_i2c_claim_bus(i2c->node)) { + debug("I2C cannot claim bus %d\n", i2c->bus_num); + return -1; + } + ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, &xaddr[4 - alen], + alen, buffer, len); + board_i2c_release_bus(i2c->node); + if (ret) { + debug("I2c read: failed %d\n", ret); + return 1; + } + return 0; +} + +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + struct s3c24x0_i2c_bus *i2c; + uchar xaddr[4]; + int ret; + + if (alen > 4) { + debug("I2C write: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + if (board_i2c_claim_bus(i2c->node)) { + debug("I2C cannot claim bus %d\n", i2c->bus_num); + return -1; + } + ret = i2c_transfer(i2c->regs, I2C_WRITE, chip << 1, &xaddr[4 - alen], + alen, buffer, len); + board_i2c_release_bus(i2c->node); + + return ret != 0; +} diff --git a/src/cpu/samsung/s5p-common/s3c24x0_i2c.h b/src/cpu/samsung/s5p-common/s3c24x0_i2c.h new file mode 100644 index 0000000..eb68af7 --- /dev/null +++ b/src/cpu/samsung/s5p-common/s3c24x0_i2c.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _S3C24X0_I2C_H +#define _S3C24X0_I2C_H + +/* FIXME: gross hack */ +#include "cpu/samsung/exynos5250/periph.h" + +struct s3c24x0_i2c { + u32 iiccon; + u32 iicstat; + u32 iicadd; + u32 iicds; + u32 iiclc; +}; + +struct s3c24x0_i2c_bus { + int node; /* device tree node */ + int bus_num; /* i2c bus number */ + struct s3c24x0_i2c *regs; + enum periph_id id; +}; +#endif /* _S3C24X0_I2C_H */ From gerrit at coreboot.org Thu Jan 3 00:41:44 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 3 Jan 2013 00:41:44 +0100 Subject: [coreboot] Patch set updated for coreboot: 1fc6137 Fix strcpy() References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2062 -gerrit commit 1fc61372dc598b11754e2cecb24ba4a118297bcd Author: Stefan Reinauer Date: Wed Dec 19 11:22:07 2012 -0800 Fix strcpy() 'nough said. It was broken since 2006. Change-Id: I312ac07eee65d6bb8567851dd38064c7f51b3bd2 Signed-off-by: Stefan Reinauer --- src/include/string.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/include/string.h b/src/include/string.h index 708961b..44f244c 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -69,10 +69,15 @@ static inline char *strncpy(char *to, const char *from, int count) return ret; } -static inline void strcpy(char *dst, const char *src) +static inline char *strcpy(char *dst, const char *src) { + char *ptr = dst; + while (*src) *dst++ = *src++; + *dst = '\0'; + + return ptr; } static inline int strcmp(const char *s1, const char *s2) From gerrit at coreboot.org Thu Jan 3 00:47:05 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 3 Jan 2013 00:47:05 +0100 Subject: [coreboot] New patch to review for coreboot: a65ef0f cbmem utility: support command line options References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2091 -gerrit commit a65ef0f5c38a65049f1d460c3d25b6beeeff0324 Author: Stefan Reinauer Date: Wed Jan 2 15:43:56 2013 -0800 cbmem utility: support command line options The tool could print much more useful information than just time stamps, for example the cbmem console on systems that don't have a kernel patched to support /sys/firmware/log. Hence, add command line option parsing to make adding such features easier in the future. Change-Id: Ib2b2584970f8a4e4187da803fcc5a95469f23a6a Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 31950e2..1cb7b8d 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "stdlib.h" #include "boot/coreboot_tables.h" @@ -32,6 +34,8 @@ typedef uint64_t u64; #include "cbmem.h" #include "timestamp.h" +#define CBMEM_VERSION "1.0" + /* File descriptor used to access /dev/mem */ static FILE* fd; @@ -246,11 +250,58 @@ static void dump_timestamps(const struct timestamp_table *tst_p) } } +void print_version(void) +{ + printf("cbmem v%s -- ", CBMEM_VERSION); + printf("Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.\n\n"); + printf( + "This program is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, version 2 of the License.\n\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program. If not, see .\n\n"); +} + +void print_usage(const char *name) +{ + printf("usage: %s [-vh?]\n", name); + printf("\n" + " -v | --version: print the version\n" + " -h | --help: print this help\n" + "\n"); + exit(1); +} int main(int argc, char** argv) { int j; - static const int possible_base_addresses[] = {0, 0xf0000}; + static const int possible_base_addresses[] = { 0, 0xf0000 }; + + int opt, option_index = 0; + static struct option long_options[] = { + {"version", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + while ((opt = getopt_long(argc, argv, "vh?", + long_options, &option_index)) != EOF) { + switch (opt) { + case 'v': + print_version(); + exit(0); + break; + case 'h': + case '?': + default: + print_usage(argv[0]); + exit(0); + break; + } + } fd = fopen("/dev/mem", "r"); if (!fd) { From gerrit at coreboot.org Thu Jan 3 00:57:00 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 00:57:00 +0100 Subject: [coreboot] Patch merged into coreboot/master: 2c3f260 Fix strcpy() References: Message-ID: the following patch was just integrated into master: commit 2c3f2609ca30f6303cec9639bacf1eb40aeee213 Author: Stefan Reinauer Date: Wed Dec 19 11:22:07 2012 -0800 Fix strcpy() 'nough said. It was broken since 2006. Change-Id: I312ac07eee65d6bb8567851dd38064c7f51b3bd2 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2062 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks Build-Tested: build bot (Jenkins) at Thu Jan 3 00:52:42 2013, giving +1 See http://review.coreboot.org/2062 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 01:09:51 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 01:09:51 +0100 Subject: [coreboot] Patch merged into coreboot/master: 1e0e556 cbmem utility: support command line options References: Message-ID: the following patch was just integrated into master: commit 1e0e55615f86bb9237fa8f4d81158cbf25c65565 Author: Stefan Reinauer Date: Wed Jan 2 15:43:56 2013 -0800 cbmem utility: support command line options The tool could print much more useful information than just time stamps, for example the cbmem console on systems that don't have a kernel patched to support /sys/firmware/log. Hence, add command line option parsing to make adding such features easier in the future. Change-Id: Ib2b2584970f8a4e4187da803fcc5a95469f23a6a Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2091 Reviewed-by: Vadim Bendebury Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Thu Jan 3 01:03:40 2013, giving +1 See http://review.coreboot.org/2091 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 03:15:24 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 3 Jan 2013 03:15:24 +0100 Subject: [coreboot] New patch to review for coreboot: 96221a7 add user-specified offset when creating armv7 cbfs image References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2092 -gerrit commit 96221a764767bd54a1b2e508cc18cbc4dcef6df9 Author: David Hendricks Date: Wed Jan 2 17:29:00 2013 -0800 add user-specified offset when creating armv7 cbfs image The "offs" provided on the command-line was not taken into account when creating an image for armv7... Change-Id: I1781bd636f60c00581f3bd1d54506f0f50bb8ad0 Signed-off-by: David Hendricks --- util/cbfstool/common.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index 7e33c97..befdc3f 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -567,10 +567,10 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize, // should be aligned to align but then we need to dynamically // create the jump to the bootblock - loadfile(bootblock, &bootblocksize, romarea + 0x20 + + loadfile(bootblock, &bootblocksize, romarea + offs + 0x20 + sizeof(struct cbfs_header), SEEK_SET); - master_header = (struct cbfs_header *)(romarea + 0x20); - uint32_t *arm_vec = (uint32_t *)romarea; + master_header = (struct cbfs_header *)(romarea + offs + 0x20); + uint32_t *arm_vec = (uint32_t *)(romarea + offs); /* * Encoding for this branch instruction is: * 31:28 - condition (0xe for always/unconditional) @@ -591,16 +591,15 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize, ALIGN((0x40 + bootblocksize), align)); master_header->architecture = htonl(CBFS_ARCHITECTURE_ARMV7); - ((uint32_t *) phys_to_virt(0x4))[0] = + ((uint32_t *) phys_to_virt(0x4 + offs))[0] = virt_to_phys(master_header); recalculate_rom_geometry(romarea); cbfs_create_empty_file( - ALIGN((0x40 + bootblocksize), align), - romsize - ALIGN((bootblocksize + 0x40), align) - //- sizeof(struct cbfs_header) - - sizeof(struct cbfs_file) ); + offs + ALIGN((0x40 + bootblocksize), align), + romsize - offs - sizeof(struct cbfs_file) - + ALIGN((bootblocksize + 0x40), align)); break; case CBFS_ARCHITECTURE_X86: From gerrit at coreboot.org Thu Jan 3 03:15:25 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 3 Jan 2013 03:15:25 +0100 Subject: [coreboot] New patch to review for coreboot: 535a8af snow: Stuff to support building image with BL1 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2093 -gerrit commit 535a8af278eb17bbfe1770d067912c0adca67d4d Author: David Hendricks Date: Wed Jan 2 17:41:51 2013 -0800 snow: Stuff to support building image with BL1 This patch does two things which will take effect in follow-up patches: 1. Add an intermediate Makefile rule for dd'ing BL1 into the coreboot.rom pre-image. This is modeled after a similar hack for the bd82x6x southbridge. 2. Add a Kconfig variable, BOOTBLOCK_OFFSET, which will be used to pass the bootblock offset into cbfstool. Change-Id: I89da255dc903c387b754b06a11bb3439035ead87 Signed-off-by: David Hendricks --- src/cpu/samsung/exynos5250/Kconfig | 7 +++++++ src/cpu/samsung/exynos5250/Makefile.inc | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig index c2d9b9f..360c57f 100644 --- a/src/cpu/samsung/exynos5250/Kconfig +++ b/src/cpu/samsung/exynos5250/Kconfig @@ -1,3 +1,10 @@ +config BOOTBLOCK_OFFSET + hex "Bootblock offset" + default 0x3400 + help + This is where the Coreboot bootblock resides. For Exynos5250, + this value is pre-determined by the vendor-provided BL1. + config EXYNOS_ACE_SHA bool default n diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index 556631a..1ff2327 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -1,3 +1,8 @@ +# Run an intermediate step when producing coreboot.rom +# that adds additional components to the final firmware +# image outside of CBFS +INTERMEDIATE += exynos5250_add_bl1 + romstage-y += clock.c romstage-y += clock_init.c romstage-y += exynos_cache.c @@ -30,3 +35,8 @@ ramstage-y += uart.c ramstage-$(CONFIG_SPL_BUILD) += lowlevel_init_c.c ramstage-$(CONFIG_SPL_BUILD) += dmc_common.c ramstage-$(CONFIG_SPL_BUILD) += dmc_init_ddr3.c + +exynos5250_add_bl1: $(obj)/coreboot.pre + printf " DD Adding Samsung Exynos5250 BL1\n" + dd if=3rdparty/cpu/samsung/exynos5250/E5250.nbl1.bin \ + of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 From gerrit at coreboot.org Thu Jan 3 03:15:25 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 3 Jan 2013 03:15:25 +0100 Subject: [coreboot] New patch to review for coreboot: cd89cd3 armv7: pass bootblock offset from Kconfig into cbfstool References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2094 -gerrit commit cd89cd38fad64dc3c27cdab91d9df2568d203e8f Author: David Hendricks Date: Wed Jan 2 17:47:11 2013 -0800 armv7: pass bootblock offset from Kconfig into cbfstool This replaces a somewhat useless calculation used earlier (which always evaluated to 0) with an offset to specify the location of the Coreboot bootblock. Change-Id: Ib85aaccf138cebeb6bf8aedf82308861206dff48 Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index b413d3e..f911591 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -49,7 +49,7 @@ prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) $(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \ -B $(objcbfs)/bootblock.bin -a 64 \ - -o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) )) + -o $(CONFIG_BOOTBLOCK_OFFSET) $(prebuild-files) true mv $@.tmp $@ else From gerrit at coreboot.org Thu Jan 3 03:15:26 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 3 Jan 2013 03:15:26 +0100 Subject: [coreboot] New patch to review for coreboot: 23c7a57 armv7: invoke intermediate build rules References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit 23c7a570333e67bd204eb13e6eb95cfc5f52a74a Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index f911591..8a728a6 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Thu Jan 3 06:41:37 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:41:37 +0100 Subject: [coreboot] Patch merged into coreboot/master: 8583ac3 armv7: create init.S for early ARMv7 init References: Message-ID: the following patch was just integrated into master: commit 8583ac390a23a09c4bf75b3b9a9f2294d0523d87 Author: David Hendricks Date: Thu Dec 27 15:23:57 2012 -0800 armv7: create init.S for early ARMv7 init The old start.S file did a lot of work and had AP-specific #ifndef's. The new init.S will eventually contain only bare minimum generic ARM code for use by the bootblock. Processor-specific stuff and things that take place later in the boot process should go elsewhere. Change-Id: I7db0a77ee4bbad1ddecb193ea125d8941a50532b Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2083 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Wed Jan 2 23:23:00 2013, giving +1 Reviewed-By: Ronald G. Minnich at Thu Jan 3 06:41:36 2013, giving +2 See http://review.coreboot.org/2083 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 06:41:56 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:41:56 +0100 Subject: [coreboot] Patch merged into coreboot/master: d3c7530 import SPL files for board_i2c_{claim, release}_bus() References: Message-ID: the following patch was just integrated into master: commit d3c7530908463537c38d84d47d0c29a3bc5dac63 Author: David Hendricks Date: Thu Dec 27 15:11:27 2012 -0800 import SPL files for board_i2c_{claim,release}_bus() This imports SPL (second phase loader) files from U-Boot. Most of the content of these files will eventually go away since they're fairly U-Boot specific. For now they are here to make Jenkins happy. Change-Id: Ib3a365ecb9dc304b20f7c1c06665aad2c0c53e69 Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2081 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin Build-Tested: build bot (Jenkins) at Wed Jan 2 23:30:44 2013, giving +1 See http://review.coreboot.org/2081 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 06:42:17 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:42:17 +0100 Subject: [coreboot] Patch merged into coreboot/master: 45256b3 Add (hacked-up) s3c24x0_i2c files References: Message-ID: the following patch was just integrated into master: commit 45256b3bfc18c2b1183238738d3f97474583b949 Author: David Hendricks Date: Thu Dec 27 14:06:05 2012 -0800 Add (hacked-up) s3c24x0_i2c files These are needed for communicating with the PMIC on Snow. We'll tidy them up as we go along... Change-Id: I197f59927eae0ad66191862d052de2a8873fb22f Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2078 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin Build-Tested: build bot (Jenkins) at Wed Jan 2 23:52:09 2013, giving +1 See http://review.coreboot.org/2078 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 06:45:27 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:45:27 +0100 Subject: [coreboot] Patch merged into coreboot/master: 454856b add user-specified offset when creating armv7 cbfs image References: Message-ID: the following patch was just integrated into master: commit 454856b274ed81babdcea4b4ed5fb922fe0caf89 Author: David Hendricks Date: Wed Jan 2 17:29:00 2013 -0800 add user-specified offset when creating armv7 cbfs image The "offs" provided on the command-line was not taken into account when creating an image for armv7... Change-Id: I1781bd636f60c00581f3bd1d54506f0f50bb8ad0 Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2092 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Thu Jan 3 03:22:44 2013, giving +1 Reviewed-By: Ronald G. Minnich at Thu Jan 3 06:45:24 2013, giving +2 See http://review.coreboot.org/2092 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 06:46:10 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:46:10 +0100 Subject: [coreboot] Patch merged into coreboot/master: 4c2245e snow: Stuff to support building image with BL1 References: Message-ID: the following patch was just integrated into master: commit 4c2245eb67b0eabf18fc9b6788bc05d962ef5e0e Author: David Hendricks Date: Wed Jan 2 17:41:51 2013 -0800 snow: Stuff to support building image with BL1 This patch does two things which will take effect in follow-up patches: 1. Add an intermediate Makefile rule for dd'ing BL1 into the coreboot.rom pre-image. This is modeled after a similar hack for the bd82x6x southbridge. 2. Add a Kconfig variable, BOOTBLOCK_OFFSET, which will be used to pass the bootblock offset into cbfstool. Change-Id: I89da255dc903c387b754b06a11bb3439035ead87 Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2093 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Thu Jan 3 03:30:35 2013, giving +1 Reviewed-By: Ronald G. Minnich at Thu Jan 3 06:46:08 2013, giving +2 See http://review.coreboot.org/2093 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 06:46:41 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 06:46:41 +0100 Subject: [coreboot] Patch merged into coreboot/master: ec8d35f armv7: pass bootblock offset from Kconfig into cbfstool References: Message-ID: the following patch was just integrated into master: commit ec8d35fe911ab35a5f40fd5b452f5463857b244a Author: David Hendricks Date: Wed Jan 2 17:47:11 2013 -0800 armv7: pass bootblock offset from Kconfig into cbfstool This replaces a somewhat useless calculation used earlier (which always evaluated to 0) with an offset to specify the location of the Coreboot bootblock. Change-Id: Ib85aaccf138cebeb6bf8aedf82308861206dff48 Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2094 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Thu Jan 3 03:37:38 2013, giving +1 Reviewed-By: Ronald G. Minnich at Thu Jan 3 06:46:35 2013, giving +2 See http://review.coreboot.org/2094 for details. -gerrit From rminnich at gmail.com Thu Jan 3 05:25:15 2013 From: rminnich at gmail.com (ron minnich) Date: Wed, 2 Jan 2013 20:25:15 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: My take on it is that people are optimistic about solving the problems (good) but I'm pretty sure it's going to be a long and unpleasant trip. I don't know why they don't take all the effort they're putting into this and put it into more open systems instead. ron On Wed, Jan 2, 2013 at 11:28 AM, David Hubbard wrote: > On Wed, Jan 2, 2013 at 11:04 AM, ron minnich wrote: >> >> On Wed, Jan 2, 2013 at 9:58 AM, Andrew Goodbody >> wrote: >> >> > I am sure that it is the old story, most testing will be done against >> > Windows. Anything more will be the exception. This is where the pressure >> > needs to be put on the platform vendors as this is the part that they >> > are >> > responsible for. >> >> Sorry, vendors don't have a pattern of paying attention to end user >> sales issues such as "won't boot Linux". They are selling into a >> market in which Linux is about 1% at best of sales. That's been the >> common experience anyway, even at very large companies: BIOS issues >> just don't get fixed. >> > > Andrew, Ron, what's your take on http://mjg59.dreamwidth.org/20916.html ? > > Specifically: > "This is part of Windows 8's fast boot support - the keyboard may not be > initialised until after the OS has started." > > So the logic goes: > 1. Secure Boot enabled and Win8 installed by the OEM > > 2. To access the BIOS, press F2/F8/DEL/whatever > > 3. "Fast boot" (hey! coreboot delivered on that first!) skips keyboard init > > 4. User is thus *forced* to use Win8's "hold down shift and restart" feature > -- adding another barrier before a user can boot her own OS. > > I think the biggest problem here is that the entire BIOS is made > inaccessible, and only if Windows gives permission can you change that. > > Regards, > David From rminnich at gmail.com Wed Jan 2 18:08:16 2013 From: rminnich at gmail.com (ron minnich) Date: Wed, 2 Jan 2013 09:08:16 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> Message-ID: On Mon, Dec 31, 2012 at 11:23 AM, David Hubbard wrote: > Andrew has good points. Technically there's nothing about Secure Boot that > can be proven to exclude alternative OS's such as Linux. While that is technically true, I am starting to see reports of systems that, at the very least, are making it hard to boot anything but Windows. Also. Microsoft has exercised its power to limit the types of binaries that will be signed, e.g. anything built with GPL V3 will not be signed. Now, while they may have valid reasons, this does demonstrate the extent of Microsoft's power over platforms with Secure Boot. I find it worrisome. Given what a mess the vendors have made of $PIR/_MP/ACPI over the years, I don't see the UEFI Secure Boot situation being much better. So, get ready for desktops/laptops that "should" boot non-Windows OSes, but don't. Garret's blog is well worth reading on this whole issue. ron From gerrit at coreboot.org Thu Jan 3 17:27:31 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 17:27:31 +0100 Subject: [coreboot] New patch to review for coreboot: bcfe3a6 Add the push default to 'make gitconfig' References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2096 -gerrit commit bcfe3a64fbfa64e09178f2a4bb7555ccbe2da538 Author: Ronald G. Minnich Date: Thu Jan 3 08:26:09 2013 -0800 Add the push default to 'make gitconfig' It's too easy to forget this and it's kind of important, so Just Add It. Change-Id: Ic7ab7658425a98d5d435bfef46f89cc6a56c7284 Signed-off-by: Ronald G. Minnich --- Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.inc b/Makefile.inc index b0a5341..a066e25 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -340,6 +340,7 @@ gitconfig: chmod +x .git/hooks/$$hook; \ fi; \ done + git config remote.origin.push HEAD:refs/for/master (git config --global user.name >/dev/null && git config --global user.email >/dev/null) || (printf 'Please configure your name and email in git:\n\n git config --global user.name "Your Name Comes Here"\n git config --global user.email your.email at example.com\n'; exit 1) crossgcc: clean-for-update From gerrit at coreboot.org Thu Jan 3 17:30:16 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 17:30:16 +0100 Subject: [coreboot] Patch set updated for coreboot: 2f8e7ac make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 2f8e7ace9b4a6d0373c32cdbec24f61fba12c13f Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H From gerrit at coreboot.org Thu Jan 3 17:30:38 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 17:30:38 +0100 Subject: [coreboot] Patch set updated for coreboot: c792fe5 make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit c792fe553bce0a0ad06d47f4da777a9e2911a3d0 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- src/include/uart8250.h | 1 - 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..3366975 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -125,7 +125,6 @@ void uart8250_tx_flush(unsigned base_port); * have three different sets of uart code, so it's an improvement. */ void uart8250_init(unsigned base_port, unsigned divisor); -void uart_init(void); #endif #if CONFIG_CONSOLE_SERIAL8250MEM void uartmem_init(void); From gerrit at coreboot.org Thu Jan 3 18:01:58 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 18:01:58 +0100 Subject: [coreboot] Patch set updated for coreboot: 7c00b43 make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 7c00b43418ef421d946cc33a7afa50e1bc36cc70 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 4 ---- src/include/uart8250.h | 1 - 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..ea371c4 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,10 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ #ifndef UART_H diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From gerrit at coreboot.org Thu Jan 3 18:43:45 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 18:43:45 +0100 Subject: [coreboot] Patch set updated for coreboot: 1f6b08a make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 1f6b08ad5bafa426c813bd09ec6c268c3c23160a Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/include/uart.h | 13 +++++++------ src/include/uart8250.h | 1 - 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..c592cfc 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,20 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#include unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); -void uart_init(void); - #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From ehaouas at noos.fr Thu Jan 3 18:30:58 2013 From: ehaouas at noos.fr (ehaouas at noos.fr) Date: Thu, 3 Jan 2013 18:30:58 +0100 (CET) Subject: [coreboot] Will coreboot work on 945G-M4 (NEC) // ECS 945G-NM uATX Motherboard In-Reply-To: Message-ID: An HTML attachment was scrubbed... URL: From gerrit at coreboot.org Thu Jan 3 18:52:18 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 18:52:18 +0100 Subject: [coreboot] Patch set updated for coreboot: 7a9173a make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 7a9173aefd7d1cafa31b00cfe6d299b64e3ee32c Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/cpu/samsung/exynos5250/uart.c | 4 ++-- src/include/uart.h | 13 +++++++------ src/include/uart8250.h | 1 - 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..b9299fd 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -218,12 +218,12 @@ static const struct console_driver exynos5_uart_console __console = { //unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; //void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; /* FIXME: trivial wrappers */ -void uart_init() +void uart_init(void) { exynos5_init_dev(); } -unsigned char uart_rx_byte() +unsigned char uart_rx_byte(void) { return exynos5_uart_rx_byte(); } diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..c592cfc 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,20 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#include unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); -void uart_init(void); - #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From gerrit at coreboot.org Thu Jan 3 18:59:50 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 18:59:50 +0100 Subject: [coreboot] Patch set updated for coreboot: 70c3a2b make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 70c3a2b966d84ba87f0adb426326777fe88ff521 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/cpu/samsung/exynos5250/uart.c | 4 ++-- src/include/uart.h | 15 +++++++++------ src/include/uart8250.h | 1 - 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..b9299fd 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -218,12 +218,12 @@ static const struct console_driver exynos5_uart_console __console = { //unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; //void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; /* FIXME: trivial wrappers */ -void uart_init() +void uart_init(void) { exynos5_init_dev(); } -unsigned char uart_rx_byte() +unsigned char uart_rx_byte(void) { return exynos5_uart_rx_byte(); } diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..a95f6ee 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,22 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#include +#ifndef __ROMCC__ unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); - -void uart_init(void); +#endif #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From gerrit at coreboot.org Thu Jan 3 19:11:34 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 19:11:34 +0100 Subject: [coreboot] Patch set updated for coreboot: aba2f85 make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit aba2f85de3a85b2a3e38b7c863ce76254db17614 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. uart.h now includes all .h files for all uarts. All 2 of them. This is actually a simplifying change. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/cpu/samsung/exynos5250/uart.c | 5 ++--- src/cpu/samsung/exynos5250/uart.h | 1 + src/include/uart.h | 16 ++++++++++------ src/include/uart8250.h | 1 - 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..17ea17e 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -34,7 +34,6 @@ #include #include -#include #define RX_FIFO_COUNT_MASK 0xff #define RX_FIFO_FULL_MASK (1 << 8) @@ -218,12 +217,12 @@ static const struct console_driver exynos5_uart_console __console = { //unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; //void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; /* FIXME: trivial wrappers */ -void uart_init() +void uart_init(void) { exynos5_init_dev(); } -unsigned char uart_rx_byte() +unsigned char uart_rx_byte(void) { return exynos5_uart_rx_byte(); } diff --git a/src/cpu/samsung/exynos5250/uart.h b/src/cpu/samsung/exynos5250/uart.h index 8190c67..033d605 100644 --- a/src/cpu/samsung/exynos5250/uart.h +++ b/src/cpu/samsung/exynos5250/uart.h @@ -68,4 +68,5 @@ static inline int s5p_uart_divslot(void) return 0; } +void uart_init(void); #endif diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..1c9ef70 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,23 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#include +#include +#ifndef __ROMCC__ unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); - -void uart_init(void); +#endif #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From gerrit at coreboot.org Thu Jan 3 19:32:30 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 19:32:30 +0100 Subject: [coreboot] Patch merged into coreboot/master: 64b364d Add the push default to 'make gitconfig' References: Message-ID: the following patch was just integrated into master: commit 64b364d1ec85f97fe948ba41cf8e7a3f43503829 Author: Ronald G. Minnich Date: Thu Jan 3 08:26:09 2013 -0800 Add the push default to 'make gitconfig' It's too easy to forget this and it's kind of important, so Just Add It. Change-Id: Ic7ab7658425a98d5d435bfef46f89cc6a56c7284 Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/2096 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer Build-Tested: build bot (Jenkins) at Thu Jan 3 17:38:33 2013, giving +1 Reviewed-By: Stefan Reinauer at Thu Jan 3 19:32:29 2013, giving +2 See http://review.coreboot.org/2096 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 19:33:02 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 3 Jan 2013 19:33:02 +0100 Subject: [coreboot] Patch merged into coreboot/master: 72a2eaf Rename mainboard_smi.c to smihandler.c References: Message-ID: the following patch was just integrated into master: commit 72a2eaf4d5364d5c5b7632b75d62c84f7bf490c8 Author: Patrick Georgi Date: Wed Dec 19 16:32:47 2012 +0100 Rename mainboard_smi.c to smihandler.c This mirrors the naming convention of handlers in northbridge and southbridge. Change-Id: I45d97c569991c955f0ae54ce909d8c267e9a5173 Signed-off-by: Patrick Georgi Reviewed-on: http://review.coreboot.org/2058 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones Reviewed-by: Stefan Reinauer Build-Tested: build bot (Jenkins) at Wed Dec 19 18:22:20 2012, giving +1 Reviewed-By: Stefan Reinauer at Sat Dec 29 17:40:48 2012, giving +2 See http://review.coreboot.org/2058 for details. -gerrit From gerrit at coreboot.org Thu Jan 3 19:34:00 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 19:34:00 +0100 Subject: [coreboot] Patch set updated for coreboot: 06ee2ef make early serial console support more generic References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 06ee2effa2137b72289629cabdae5f7c8f9b7de1 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. uart.h now includes all .h files for all uarts. All 2 of them. This is actually a simplifying change. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/cpu/samsung/exynos5250/uart.c | 6 +++--- src/cpu/samsung/exynos5250/uart.h | 1 + src/include/uart.h | 22 ++++++++++++++++------ src/include/uart8250.h | 1 - 8 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..a726c1f 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + select SERIAL_CONSOLE + default n + help + Use serial console during early boot stages (e.g. cache-as-RAM) + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..e92dbf6 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_SERIAL_CONSOLE && !CONFIG_CONSOLE_SERIAL8250MEM uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..2d7bf38 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -23,6 +23,7 @@ //#include //#include +#include #include #include //#include @@ -34,7 +35,6 @@ #include #include -#include #define RX_FIFO_COUNT_MASK 0xff #define RX_FIFO_FULL_MASK (1 << 8) @@ -218,12 +218,12 @@ static const struct console_driver exynos5_uart_console __console = { //unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; //void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; /* FIXME: trivial wrappers */ -void uart_init() +void uart_init(void) { exynos5_init_dev(); } -unsigned char uart_rx_byte() +unsigned char uart_rx_byte(void) { return exynos5_uart_rx_byte(); } diff --git a/src/cpu/samsung/exynos5250/uart.h b/src/cpu/samsung/exynos5250/uart.h index 8190c67..033d605 100644 --- a/src/cpu/samsung/exynos5250/uart.h +++ b/src/cpu/samsung/exynos5250/uart.h @@ -68,4 +68,5 @@ static inline int s5p_uart_divslot(void) return 0; } +void uart_init(void); #endif diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..6628314 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,29 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#if CONFIG_CONSOLE_SERIAL8250 +#include +#endif + +#if CONFIG_CPU_SAMSUNG_EXYNOS5 +#include +#endif + +#ifndef __ROMCC__ unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); - -void uart_init(void); +#endif #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From rminnich at gmail.com Thu Jan 3 19:40:21 2013 From: rminnich at gmail.com (ron minnich) Date: Thu, 3 Jan 2013 13:40:21 -0500 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: OK, after further thought, here's my take. Two companies have defined a secure boot standard in such a way that they can closely control what boots on future systems using the one company's chips. This is a sea change from the original IBM PC design, which encouraged people to boot anything, and included the (copyrighted) BIOS listing on paper to further that end. The current state is that the software company is becoming the gatekeeper for what OS will run on systems built using the hardware company's chips. Their end goal is that the software company becomes the gatekeeper for what runs on almost *anything* -- not just x86. Don't believe me? Read about ARM systems and Windows 8. Vendors are now building systems based on this standard. People are seeing that the situation is not quite as blissful as the two companies have painted it -- that certain software will in fact be locked out for a number of reasons, that there can be unexplained delays in getting code signed, and that buggy EFI implementations may lock people out in unforeseen ways. The open source community's response has been to act in a way that strengthens this model. They're doing all they can to find a way to work inside these limits. Instead of pushing hard to use only hardware that's really open, and doing what they can to relegate this (shown to be insecure) "secure" boot to the dustbin of history, they're pushing as hard as they can to make it succeed. I find this quite perverse. There's lots of good hardware out there that is not built around this lockin, and yet the open source community is focusing lots of effort on making the lockin viable. The open source community has pushed back on defective standards like this before and won. Why they're rolling over now is a puzzling, especially given the existence of alternatives. Put another way, I think the secure boot standard needs the open source community more than the open source community needs the secure boot standard, but the open source community is not exploiting that fact. I guess part of it is that so much of the open source community is contained in big companies, but it's stil disappointing. ron From gerrit at coreboot.org Thu Jan 3 19:54:12 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 19:54:12 +0100 Subject: [coreboot] Patch set updated for coreboot: 9c32571 cleanup some exynos5250 uart code References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2084 -gerrit commit 9c32571a12fb1ca1f635208af6bb0e99df784fed Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. A bit of cleanup based on earlier patches. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/cpu/samsung/exynos5250/uart.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 2d7bf38..b219f48 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -21,15 +21,9 @@ * */ -//#include -//#include #include #include #include -//#include -//#include -//#include -//#include #include /* for __console definition */ @@ -180,8 +174,6 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -/* FIXME: ordering of arguments for coreboot v. u-boot for tx_byte */ -//static void exynos5_tx_byte(const char c, const int dev_index) static void exynos5_uart_tx_byte(unsigned char data) { // struct s5p_uart *const uart = s5p_get_base_uart(dev_index); @@ -198,14 +190,6 @@ static void exynos5_uart_tx_byte(unsigned char data) #ifndef __PRE_RAM__ static const struct console_driver exynos5_uart_console __console = { -//static const struct console_driver exynos5_uart_console __console = { -#if 0 - void (*init)(void); - void (*tx_byte)(unsigned char byte); - void (*tx_flush)(void); - unsigned char (*rx_byte)(void); - int (*tst_byte)(void); -#endif .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, // .tx_flush = exynos5_uart_tx_flush, @@ -213,11 +197,6 @@ static const struct console_driver exynos5_uart_console __console = { // .tst_byte = exynos5_uart_tst_byte, }; #else -/* for romstage_console... */ -//void (*uart_init)(void) = exynos5_init_dev; -//unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; -//void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; -/* FIXME: trivial wrappers */ void uart_init(void) { exynos5_init_dev(); From gerrit at coreboot.org Thu Jan 3 19:54:13 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 19:54:13 +0100 Subject: [coreboot] Patch set updated for coreboot: dfd5047 enable early serial console on exynos5250 References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2085 -gerrit commit dfd50470e66b2f6017e65fcd3b17797a0010d04a Author: David Hendricks Date: Mon Dec 31 17:55:29 2012 -0800 enable early serial console on exynos5250 Change-Id: Ib16308c72b86860e80caec96202c42991a7b1d1a Signed-off-by: David Hendricks --- src/cpu/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 4a09ca3..abfc049 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 select CPU_SAMSUNG_EXYNOS + select EARLY_SERIAL_CONSOLE bool default n From gerrit at coreboot.org Thu Jan 3 22:22:49 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 22:22:49 +0100 Subject: [coreboot] Patch set updated for coreboot: 3275900 update CFLAGS for armv7 References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2075 -gerrit commit 3275900df69bc56d723f17abc5f88250ac9a4b31 Author: David Hendricks Date: Thu Dec 27 13:30:55 2012 -0800 update CFLAGS for armv7 This updates $CFLAGS used for armv7. Most of them were just added to be consistent with what u-boot does. The important ones here are -march=armv7-a and -mthumb (to allow 16-bit Thumb instructions). I removed the hard float support because it got errors and coreboot should never use floats anyway. We're still having trouble with enums but I want to see how far it gets with this patch. Depends-On: I6f730d017391f9ec4401cdfd34931c869df10a9e Change-Id: Ia8a1ae22959933e06f7b996d1832cea40819f1ff Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- util/xcompile/xcompile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile index 4239176..db58648 100644 --- a/util/xcompile/xcompile +++ b/util/xcompile/xcompile @@ -106,14 +106,16 @@ detect_special_flags() { CFLAGS="$CFLAGS -Wl,--build-id=none" case "$architecture" in - arm ) - # testcc "$CC" "$CFLAGS -mcpu=cortex-a9" && - # CFLAGS="$CFLAGS -mcpu=cortex-a9" + armv7 ) testcc "$CC" "\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" && CFLAGS="\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" +$CFLAGS -fno-common -ffixed-r8 -marm -mabi=aapcs-linux -march=armv7-a \ +-mthumb -mthumb-interwork -mfloat-abi=hard -fno-builtin -pipe \ +-mno-unaligned-access -Werror -Wall -Wno-format-nonliteral \ +-Wno-format-security" && CFLAGS="\ +$CFLAGS -fno-common -ffixed-r8 -marm -mabi=aapcs-linux -march=armv7-a \ +-mthumb -mthumb-interwork -mfloat-abi=hard -fno-builtin -pipe \ +-mno-unaligned-access -Werror -Wall -Wno-format-nonliteral \ +-Wno-format-security" ;; esac } From gerrit at coreboot.org Thu Jan 3 22:37:35 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Thu, 3 Jan 2013 22:37:35 +0100 Subject: [coreboot] Patch set updated for coreboot: 5605707 update CFLAGS for armv7 References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2075 -gerrit commit 5605707c208935ecefd07c4430ff7a053315ddeb Author: David Hendricks Date: Thu Dec 27 13:30:55 2012 -0800 update CFLAGS for armv7 This updates $CFLAGS used for armv7. Most of them were just added to be consistent with what u-boot does. The important ones here are -march=armv7-a and -mthumb (to allow 16-bit Thumb instructions). I removed the hard float support because it got errors and coreboot should never use floats anyway. We're still having trouble with enums but I want to see how far it gets with this patch. Also, put the flags in a form that makes diffs easier to read. It's almost impossible otherwise. Depends-On: I6f730d017391f9ec4401cdfd34931c869df10a9e Change-Id: Ia8a1ae22959933e06f7b996d1832cea40819f1ff Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- util/xcompile/xcompile | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile index 4239176..d800ba0 100644 --- a/util/xcompile/xcompile +++ b/util/xcompile/xcompile @@ -106,14 +106,21 @@ detect_special_flags() { CFLAGS="$CFLAGS -Wl,--build-id=none" case "$architecture" in - arm ) - # testcc "$CC" "$CFLAGS -mcpu=cortex-a9" && - # CFLAGS="$CFLAGS -mcpu=cortex-a9" - testcc "$CC" "\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" && CFLAGS="\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" + armv7 ) + ARMFLAGS="\ + -fno-builtin\ + -fno-common-ffixed-r8\ + -mabi=aapcs-linux\ + -march=armv7-a\ + -marm\ + -mno-unaligned-access-Werror\ + -mthumb-mthumb-interwork\ + -pipe\ + -Wall\ + -Wno-format-nonliteral\ + -Wno-format-security" + + testcc "$CC" "$CFLAGS $ARMFLAGS" && CFLAGS="$CFLAGS $ARMFLAGS" ;; esac } From gerrit at coreboot.org Thu Jan 3 23:34:31 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 3 Jan 2013 23:34:31 +0100 Subject: [coreboot] New patch to review for coreboot: 1ce9a91 cbmem utility: Use mmap instead of fseek/fread References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2097 -gerrit commit 1ce9a91d7263479f70e19d3cde1f57b0dac17845 Author: Stefan Reinauer Date: Thu Jan 3 14:30:33 2013 -0800 cbmem utility: Use mmap instead of fseek/fread The kernel on Ubuntu 12.04LTS does not allow to use fseek/fread to read the coreboot table at the end of memory but will instead abort cbmem with a "Bad Address" error. Whether that is a security feature (some variation of CONFIG_STRICT_DEVMEM) or a kernel bug is not yet clear, however using mmap works nicely. Change-Id: I796b4cd2096fcdcc65c1361ba990cd467f13877e Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 208 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 123 insertions(+), 85 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 1cb7b8d..dda50d1 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -17,14 +17,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include #include #include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define MAP_BYTES (1024*1024) -#include "stdlib.h" #include "boot/coreboot_tables.h" typedef uint16_t u16; @@ -36,8 +42,12 @@ typedef uint64_t u64; #define CBMEM_VERSION "1.0" -/* File descriptor used to access /dev/mem */ -static FILE* fd; +/* verbose output? */ +static int verbose = 0; +#define debug(x...) if(verbose) printf(x) + +/* File handle used to access /dev/mem */ +static int fd; /* * calculate ip checksum (16 bit quantities) on a passed in buffer. In case @@ -59,104 +69,113 @@ static u16 ipchcksum(const void *addr, unsigned size) } /* - * Starting at 'offset' read 'size' bytes from the previously opened /dev/mem - * into the 'buffer'. - * - * Return zero on success or exit on any error. + * Functions to map / unmap physical memory into virtual address space. These + * functions always maps 1MB at a time and can only map one area at once. */ -static int readmem(void* buffer, u32 offset, int size) +static void *mapped_virtual; +static void *map_memory(u64 physical) { - if (fseek(fd, offset, SEEK_SET)) { - fprintf(stderr, "fseek failed(%d) for offset %d\n", - errno, offset); - exit(1); - } - if (fread(buffer, 1, size, fd) != size) { - fprintf(stderr, "failed (%d) to read %d bytes at 0x%x\n", - errno, size, offset); + void *v; + off_t p; + int page = getpagesize(); + + /* Mapped memory must be aligned to page size */ + p = physical & ~(page - 1); + + debug("Mapping 1MB of physical memory at %zx.\n", p); + + v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); + + if (v == MAP_FAILED) { + fprintf(stderr, "Failed to mmap /dev/mem: %s\n", + strerror(errno)); exit(1); } - return 0; + + /* Remember what we actually mapped ... */ + mapped_virtual = v; + + /* ... but return address to the physical memory that was requested */ + v += physical & (page-1); + + return v; +} + +static void unmap_memory(void) +{ + debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); + munmap(mapped_virtual, MAP_BYTES); } /* - * Try finding the timestamp table starting from the passed in memory offset. - * Could be called recursively in case a forwarding entry is found. + * Try finding the timestamp table and coreboot cbmem console starting from the + * passed in memory offset. Could be called recursively in case a forwarding + * entry is found. * * Returns pointer to a memory buffer containg the timestamp table or zero if * none found. */ -static const struct timestamp_table *find_tstamps(u64 address) + +static struct lb_cbmem_ref timestamps; +static struct lb_cbmem_ref console; + +static int parse_cbtable(u64 address) { - int i; + int i, found = 0; + void *buf; + + debug("Looking for coreboot table at %lx\n", address); + buf = map_memory(address); /* look at every 16 bytes within 4K of the base */ + for (i = 0; i < 0x1000; i += 0x10) { - void *buf; - struct lb_header lbh; + struct lb_header *lbh; struct lb_record* lbr_p; + void *lbtable; int j; - readmem(&lbh, address + i, sizeof(lbh)); - if (memcmp(lbh.signature, "LBIO", sizeof(lbh.signature)) || - !lbh.header_bytes || - ipchcksum(&lbh, sizeof(lbh))) + lbh = (struct lb_header *)(buf + i); + if (memcmp(lbh->signature, "LBIO", sizeof(lbh->signature)) || + !lbh->header_bytes || + ipchcksum(lbh, sizeof(*lbh))) { continue; - - /* good lb_header is found, try reading the table */ - buf = malloc(lbh.table_bytes); - if (!buf) { - fprintf(stderr, "failed to allocate %d bytes\n", - lbh.table_bytes); - exit(1); } + lbtable = buf + i + lbh->header_bytes; - readmem(buf, address + i + lbh.header_bytes, lbh.table_bytes); - if (ipchcksum(buf, lbh.table_bytes) != - lbh.table_checksum) { - /* False positive or table corrupted... */ - free(buf); + if (ipchcksum(lbtable, lbh->table_bytes) != + lbh->table_checksum) { + debug("Signature found, but wrong checksum.\n"); continue; } - for (j = 0; j < lbh.table_bytes; j += lbr_p->size) { + found = 1; + debug("Found!\n"); + + for (j = 0; j < lbh->table_bytes; j += lbr_p->size) { /* look for the timestamp table */ - lbr_p = (struct lb_record*) ((char *)buf + j); + lbr_p = (struct lb_record*) ((char *)lbtable + j); + debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { case LB_TAG_TIMESTAMPS: { - struct lb_cbmem_ref *cbmr_p = - (struct lb_cbmem_ref *) lbr_p; - int new_size; - struct timestamp_table *tst_p; - u32 stamp_addr = (u32) - ((uintptr_t)(cbmr_p->cbmem_addr)); - - readmem(buf, stamp_addr, - sizeof(struct timestamp_table)); - tst_p = (struct timestamp_table *) buf; - new_size = sizeof(struct timestamp_table) + - tst_p->num_entries * - sizeof(struct timestamp_entry); - buf = realloc(buf, new_size); - if (!buf) { - fprintf(stderr, - "failed to reallocate %d bytes\n", - new_size); - exit(1); - } - readmem(buf, stamp_addr, new_size); - return buf; + debug("Found timestamp table\n"); + timestamps = *(struct lb_cbmem_ref *) lbr_p; + continue; + } + case LB_TAG_CBMEM_CONSOLE: { + debug("Found cbmem console\n"); + console = *(struct lb_cbmem_ref *) lbr_p; + continue; } case LB_TAG_FORWARD: { /* * This is a forwarding entry - repeat the * search at the new address. */ - struct lb_forward *lbf_p = - (struct lb_forward *) lbr_p; - - free(buf); - return find_tstamps(lbf_p->forward); + struct lb_forward lbf_p = + *(struct lb_forward *) lbr_p; + unmap_memory(); + return parse_cbtable(lbf_p.forward); } default: break; @@ -164,14 +183,16 @@ static const struct timestamp_table *find_tstamps(u64 address) } } - return 0; + unmap_memory(); + + return found; } /* * read CPU frequency from a sysfs file, return an frequency in Kilohertz as * an int or exit on any error. */ -static u64 get_cpu_freq_KHz() +static u64 get_cpu_freq_KHz(void) { FILE *cpuf; char freqs[100]; @@ -184,7 +205,8 @@ static u64 get_cpu_freq_KHz() cpuf = fopen(freq_file, "r"); if (!cpuf) { - fprintf(stderr, "Could not open %s\n", freq_file); + fprintf(stderr, "Could not open %s: %s\n", + freq_file, strerror(errno)); exit(1); } @@ -228,10 +250,19 @@ static void print_norm(u64 v, int comma) } /* dump the timestamp table */ -static void dump_timestamps(const struct timestamp_table *tst_p) +static void dump_timestamps(void) { int i; u64 cpu_freq_MHz = get_cpu_freq_KHz() / 1000; + struct timestamp_table *tst_p; + + if (timestamps.tag != LB_TAG_TIMESTAMPS) { + fprintf(stderr, "No timestamps found in coreboot table.\n"); + return; + } + + tst_p = (struct timestamp_table *) + map_memory((unsigned long)timestamps.cbmem_addr); printf("%d entries total:\n\n", tst_p->num_entries); for (i = 0; i < tst_p->num_entries; i++) { @@ -248,6 +279,8 @@ static void dump_timestamps(const struct timestamp_table *tst_p) } printf("\n"); } + + unmap_memory(); } void print_version(void) @@ -281,15 +314,21 @@ int main(int argc, char** argv) int j; static const int possible_base_addresses[] = { 0, 0xf0000 }; + int print_timestamps = 1; + int opt, option_index = 0; static struct option long_options[] = { + {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "vh?", + while ((opt = getopt_long(argc, argv, "Vvh?", long_options, &option_index)) != EOF) { switch (opt) { + case 'V': + verbose = 1; + break; case 'v': print_version(); exit(0); @@ -303,23 +342,22 @@ int main(int argc, char** argv) } } - fd = fopen("/dev/mem", "r"); - if (!fd) { - printf("failed to gain memory access\n"); + fd = open("/dev/mem", O_RDONLY, 0); + if (fd < 0) { + fprintf(stderr, "Failed to gain memory access: %s\n", + strerror(errno)); return 1; } + /* Find and parse coreboot table */ for (j = 0; j < ARRAY_SIZE(possible_base_addresses); j++) { - const struct timestamp_table * tst_p = - find_tstamps(possible_base_addresses[j]); - - if (tst_p) { - dump_timestamps(tst_p); - free((void*)tst_p); + if (parse_cbtable(possible_base_addresses[j])) break; - } } - fclose(fd); + if (print_timestamps) + dump_timestamps(); + + close(fd); return 0; } From gerrit at coreboot.org Thu Jan 3 23:36:02 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 3 Jan 2013 23:36:02 +0100 Subject: [coreboot] Patch set updated for coreboot: 2c470b2 cbmem utility: Use mmap instead of fseek/fread References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2097 -gerrit commit 2c470b25d6b5801a4ae81b960edb259484683179 Author: Stefan Reinauer Date: Thu Jan 3 14:30:33 2013 -0800 cbmem utility: Use mmap instead of fseek/fread The kernel on Ubuntu 12.04LTS does not allow to use fseek/fread to read the coreboot table at the end of memory but will instead abort cbmem with a "Bad Address" error. Whether that is a security feature (some variation of CONFIG_STRICT_DEVMEM) or a kernel bug is not yet clear, however using mmap works nicely. Change-Id: I796b4cd2096fcdcc65c1361ba990cd467f13877e Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 208 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 123 insertions(+), 85 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 1cb7b8d..df00684 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -17,14 +17,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include #include #include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define MAP_BYTES (1024*1024) -#include "stdlib.h" #include "boot/coreboot_tables.h" typedef uint16_t u16; @@ -36,8 +42,12 @@ typedef uint64_t u64; #define CBMEM_VERSION "1.0" -/* File descriptor used to access /dev/mem */ -static FILE* fd; +/* verbose output? */ +static int verbose = 0; +#define debug(x...) if(verbose) printf(x) + +/* File handle used to access /dev/mem */ +static int fd; /* * calculate ip checksum (16 bit quantities) on a passed in buffer. In case @@ -59,104 +69,113 @@ static u16 ipchcksum(const void *addr, unsigned size) } /* - * Starting at 'offset' read 'size' bytes from the previously opened /dev/mem - * into the 'buffer'. - * - * Return zero on success or exit on any error. + * Functions to map / unmap physical memory into virtual address space. These + * functions always maps 1MB at a time and can only map one area at once. */ -static int readmem(void* buffer, u32 offset, int size) +static void *mapped_virtual; +static void *map_memory(u64 physical) { - if (fseek(fd, offset, SEEK_SET)) { - fprintf(stderr, "fseek failed(%d) for offset %d\n", - errno, offset); - exit(1); - } - if (fread(buffer, 1, size, fd) != size) { - fprintf(stderr, "failed (%d) to read %d bytes at 0x%x\n", - errno, size, offset); + void *v; + off_t p; + int page = getpagesize(); + + /* Mapped memory must be aligned to page size */ + p = physical & ~(page - 1); + + debug("Mapping 1MB of physical memory at %zx.\n", p); + + v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); + + if (v == MAP_FAILED) { + fprintf(stderr, "Failed to mmap /dev/mem: %s\n", + strerror(errno)); exit(1); } - return 0; + + /* Remember what we actually mapped ... */ + mapped_virtual = v; + + /* ... but return address to the physical memory that was requested */ + v += physical & (page-1); + + return v; +} + +static void unmap_memory(void) +{ + debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); + munmap(mapped_virtual, MAP_BYTES); } /* - * Try finding the timestamp table starting from the passed in memory offset. - * Could be called recursively in case a forwarding entry is found. + * Try finding the timestamp table and coreboot cbmem console starting from the + * passed in memory offset. Could be called recursively in case a forwarding + * entry is found. * * Returns pointer to a memory buffer containg the timestamp table or zero if * none found. */ -static const struct timestamp_table *find_tstamps(u64 address) + +static struct lb_cbmem_ref timestamps; +static struct lb_cbmem_ref console; + +static int parse_cbtable(u64 address) { - int i; + int i, found = 0; + void *buf; + + debug("Looking for coreboot table at %lx\n", address); + buf = map_memory(address); /* look at every 16 bytes within 4K of the base */ + for (i = 0; i < 0x1000; i += 0x10) { - void *buf; - struct lb_header lbh; + struct lb_header *lbh; struct lb_record* lbr_p; + void *lbtable; int j; - readmem(&lbh, address + i, sizeof(lbh)); - if (memcmp(lbh.signature, "LBIO", sizeof(lbh.signature)) || - !lbh.header_bytes || - ipchcksum(&lbh, sizeof(lbh))) + lbh = (struct lb_header *)(buf + i); + if (memcmp(lbh->signature, "LBIO", sizeof(lbh->signature)) || + !lbh->header_bytes || + ipchcksum(lbh, sizeof(*lbh))) { continue; - - /* good lb_header is found, try reading the table */ - buf = malloc(lbh.table_bytes); - if (!buf) { - fprintf(stderr, "failed to allocate %d bytes\n", - lbh.table_bytes); - exit(1); } + lbtable = buf + i + lbh->header_bytes; - readmem(buf, address + i + lbh.header_bytes, lbh.table_bytes); - if (ipchcksum(buf, lbh.table_bytes) != - lbh.table_checksum) { - /* False positive or table corrupted... */ - free(buf); + if (ipchcksum(lbtable, lbh->table_bytes) != + lbh->table_checksum) { + debug("Signature found, but wrong checksum.\n"); continue; } - for (j = 0; j < lbh.table_bytes; j += lbr_p->size) { + found = 1; + debug("Found!\n"); + + for (j = 0; j < lbh->table_bytes; j += lbr_p->size) { /* look for the timestamp table */ - lbr_p = (struct lb_record*) ((char *)buf + j); + lbr_p = (struct lb_record*) ((char *)lbtable + j); + debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { case LB_TAG_TIMESTAMPS: { - struct lb_cbmem_ref *cbmr_p = - (struct lb_cbmem_ref *) lbr_p; - int new_size; - struct timestamp_table *tst_p; - u32 stamp_addr = (u32) - ((uintptr_t)(cbmr_p->cbmem_addr)); - - readmem(buf, stamp_addr, - sizeof(struct timestamp_table)); - tst_p = (struct timestamp_table *) buf; - new_size = sizeof(struct timestamp_table) + - tst_p->num_entries * - sizeof(struct timestamp_entry); - buf = realloc(buf, new_size); - if (!buf) { - fprintf(stderr, - "failed to reallocate %d bytes\n", - new_size); - exit(1); - } - readmem(buf, stamp_addr, new_size); - return buf; + debug("Found timestamp table\n"); + timestamps = *(struct lb_cbmem_ref *) lbr_p; + continue; + } + case LB_TAG_CBMEM_CONSOLE: { + debug("Found cbmem console\n"); + console = *(struct lb_cbmem_ref *) lbr_p; + continue; } case LB_TAG_FORWARD: { /* * This is a forwarding entry - repeat the * search at the new address. */ - struct lb_forward *lbf_p = - (struct lb_forward *) lbr_p; - - free(buf); - return find_tstamps(lbf_p->forward); + struct lb_forward lbf_p = + *(struct lb_forward *) lbr_p; + unmap_memory(); + return parse_cbtable(lbf_p.forward); } default: break; @@ -164,14 +183,16 @@ static const struct timestamp_table *find_tstamps(u64 address) } } - return 0; + unmap_memory(); + + return found; } /* * read CPU frequency from a sysfs file, return an frequency in Kilohertz as * an int or exit on any error. */ -static u64 get_cpu_freq_KHz() +static u64 get_cpu_freq_KHz(void) { FILE *cpuf; char freqs[100]; @@ -184,7 +205,8 @@ static u64 get_cpu_freq_KHz() cpuf = fopen(freq_file, "r"); if (!cpuf) { - fprintf(stderr, "Could not open %s\n", freq_file); + fprintf(stderr, "Could not open %s: %s\n", + freq_file, strerror(errno)); exit(1); } @@ -228,10 +250,19 @@ static void print_norm(u64 v, int comma) } /* dump the timestamp table */ -static void dump_timestamps(const struct timestamp_table *tst_p) +static void dump_timestamps(void) { int i; u64 cpu_freq_MHz = get_cpu_freq_KHz() / 1000; + struct timestamp_table *tst_p; + + if (timestamps.tag != LB_TAG_TIMESTAMPS) { + fprintf(stderr, "No timestamps found in coreboot table.\n"); + return; + } + + tst_p = (struct timestamp_table *) + map_memory((unsigned long)timestamps.cbmem_addr); printf("%d entries total:\n\n", tst_p->num_entries); for (i = 0; i < tst_p->num_entries; i++) { @@ -248,6 +279,8 @@ static void dump_timestamps(const struct timestamp_table *tst_p) } printf("\n"); } + + unmap_memory(); } void print_version(void) @@ -281,15 +314,21 @@ int main(int argc, char** argv) int j; static const int possible_base_addresses[] = { 0, 0xf0000 }; + int print_timestamps = 1; + int opt, option_index = 0; static struct option long_options[] = { + {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "vh?", + while ((opt = getopt_long(argc, argv, "Vvh?", long_options, &option_index)) != EOF) { switch (opt) { + case 'V': + verbose = 1; + break; case 'v': print_version(); exit(0); @@ -303,23 +342,22 @@ int main(int argc, char** argv) } } - fd = fopen("/dev/mem", "r"); - if (!fd) { - printf("failed to gain memory access\n"); + fd = open("/dev/mem", O_RDONLY, 0); + if (fd < 0) { + fprintf(stderr, "Failed to gain memory access: %s\n", + strerror(errno)); return 1; } + /* Find and parse coreboot table */ for (j = 0; j < ARRAY_SIZE(possible_base_addresses); j++) { - const struct timestamp_table * tst_p = - find_tstamps(possible_base_addresses[j]); - - if (tst_p) { - dump_timestamps(tst_p); - free((void*)tst_p); + if (parse_cbtable(possible_base_addresses[j])) break; - } } - fclose(fd); + if (print_timestamps) + dump_timestamps(); + + close(fd); return 0; } From gerrit at coreboot.org Thu Jan 3 23:49:17 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 3 Jan 2013 23:49:17 +0100 Subject: [coreboot] Patch set updated for coreboot: c173165 Implement GCC code coverage analysis References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2052 -gerrit commit c173165aaa8e92a8bb31190b0ef9029b32a350ee Author: Stefan Reinauer Date: Tue Dec 18 16:23:28 2012 -0800 Implement GCC code coverage analysis Change-Id: Ib287d8309878a1f5c4be770c38b1bc0bb3aa6ec7 Signed-off-by: Stefan Reinauer --- Makefile.inc | 3 + src/Kconfig | 18 + src/arch/x86/Makefile.inc | 2 +- src/arch/x86/boot/acpi.c | 4 + src/arch/x86/coreboot_ram.ld | 8 + src/include/cbmem.h | 1 + src/include/coverage.h | 21 + src/lib/Makefile.inc | 1 + src/lib/cbmem.c | 2 + src/lib/gcov-glue.c | 153 ++++++ src/lib/gcov-io.c | 556 ++++++++++++++++++++ src/lib/gcov-io.h | 639 +++++++++++++++++++++++ src/lib/gcov-iov.h | 4 + src/lib/hardwaremain.c | 5 + src/lib/libgcov.c | 1158 ++++++++++++++++++++++++++++++++++++++++++ src/lib/selfboot.c | 4 + 16 files changed, 2578 insertions(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index a066e25..3731797 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,6 +99,9 @@ romstage-S-ccopts:=-D__PRE_RAM__ ifeq ($(CONFIG_TRACE),y) ramstage-c-ccopts:= -finstrument-functions endif +ifeq ($(CONFIG_COVERAGE),y) +ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) diff --git a/src/Kconfig b/src/Kconfig index 0a94ed8..2c97327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,15 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail. +config COVERAGE + bool "Code coverage support" + depends on COMPILER_GCC + default n + help + Add code coverage support for coreboot. This will store code + coverage information in CBMEM for extraction from user space. + If unsure, say N. + endmenu source src/mainboard/Kconfig @@ -868,6 +877,15 @@ config TRACE the 0xaaaabbbb is the actual function and 0xccccdddd is EIP of calling function. Please note some printk releated functions are omitted from trace to have good looking console dumps. + +config DEBUG_COVERAGE + bool "Debug code coverage" + default n + depends on COVERAGE + help + If enabled, the code coverage hooks in coreboot will output some + information about the coverage data that is dumped. + endmenu # These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index e84700e..ea86f8f 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -166,7 +166,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 1d7dbf8..730e53e 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -36,6 +36,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -642,6 +643,9 @@ void suspend_resume(void) /* Call mainboard resume handler first, if defined. */ if (mainboard_suspend_resume) mainboard_suspend_resume(); +#if CONFIG_COVERAGE + coverage_exit(); +#endif post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); } diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld index a87a0e7..7ce0367 100644 --- a/src/arch/x86/coreboot_ram.ld +++ b/src/arch/x86/coreboot_ram.ld @@ -39,6 +39,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 21efe77..08e913a 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -55,6 +55,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_COVERAGE 0x47434f56 #define CBMEM_ID_NONE 0x00000000 #ifndef __ASSEMBLER__ diff --git a/src/include/coverage.h b/src/include/coverage.h new file mode 100644 index 0000000..e1c50c5 --- /dev/null +++ b/src/include/coverage.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void coverage_init(void); +void coverage_exit(void); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6b3f0d8..6796448 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -70,6 +70,7 @@ ramstage-$(CONFIG_USBDEBUG) += usbdebug.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index 7378d8c..f270f5d 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -260,6 +260,8 @@ void cbmem_list(void) case CBMEM_ID_TIMESTAMP: printk(BIOS_DEBUG, "TIME STAMP "); break; case CBMEM_ID_MRCDATA: printk(BIOS_DEBUG, "MRC DATA "); break; case CBMEM_ID_CONSOLE: printk(BIOS_DEBUG, "CONSOLE "); break; + case CBMEM_ID_ELOG: printk(BIOS_DEBUG, "ELOG "); break; + case CBMEM_ID_COVERAGE: printk(BIOS_DEBUG, "COVERAGE "); break; default: printk(BIOS_DEBUG, "%08x ", cbmem_toc[i].id); } printk(BIOS_DEBUG, "%08llx ", cbmem_toc[i].base); diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c new file mode 100644 index 0000000..7c069cb --- /dev/null +++ b/src/lib/gcov-glue.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +typedef struct file { + uint32_t magic; + struct file *next; + char *filename; + char *data; + int offset; + int len; +} FILE; + +#define SEEK_SET 0 /* Seek from beginning of file. */ + +#define DIR_SEPARATOR '/' +#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#define HAS_DRIVE_SPEC(f) (0) + +#define COVERAGE_SIZE (32*1024) + +static FILE *current_file = NULL; +static FILE *previous_file = NULL; + +static FILE *fopen(const char *path, const char *mode) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fopen %s with mode %s\n", + path, mode); +#endif + if (!current_file) { + current_file = cbmem_add(CBMEM_ID_COVERAGE, 32*1024); + } else { + previous_file = current_file; + current_file = (FILE *)(ALIGN(((unsigned long)previous_file->data + previous_file->len), 16)); + } + + // TODO check if we're at the end of the CBMEM region (ENOMEM) + if (current_file) { + current_file->magic = 0x584d4153; + current_file->next = NULL; + if (previous_file) + previous_file->next = current_file; + current_file->filename = (char *)¤t_file[1]; + strcpy(current_file->filename, path); + current_file->data = (char *)ALIGN(((unsigned long)current_file->filename + strlen(path) + 1), 16); + current_file->offset = 0; + current_file->len = 0; + } + + return current_file; +} + +static int fclose(FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fclose %s\n", stream->filename); +#endif + return 0; +} + +static int fseek(FILE *stream, long offset, int whence) +{ + /* fseek should only be called with offset==0 and whence==SEEK_SET + * to a freshly opened file. */ + gcc_assert (offset == 0 && whence == SEEK_SET); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fseek %s offset=%d whence=%d\n", + stream->filename, offset, whence); +#endif + return 0; +} + +static long ftell(FILE *stream) +{ + /* ftell should currently not be called */ + gcc_assert(0); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "ftell %s\n", stream->filename); +#endif + return 0; +} + +static size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fread: ptr=%p size=%zd nmemb=%zd FILE*=%p\n", + ptr, size, nmemb, stream); +#endif + return 0; +} + +static size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fwrite: %zd * 0x%zd bytes to file %s\n", + nmemb, size, stream->filename); +#endif + // TODO check if file is last opened file and fail otherwise. + + memcpy(stream->data + stream->offset, ptr, size * nmemb); + stream->len += (nmemb * size) - (stream->len - stream->offset); + stream->offset += nmemb * size; + return nmemb; +} + +static void setbuf(FILE *stream, char *buf) +{ + gcc_assert(buf == 0); +} + +void coverage_init(void) +{ + extern long __CTOR_LIST__; + typedef void (*func_ptr)(void) ; + func_ptr *ctor = (func_ptr*) &__CTOR_LIST__; + if (ctor == NULL) + return; + + for ( ; *ctor != (func_ptr) 0; ctor++) { + (*ctor)(); + } +} + +void __gcov_flush(void); +void coverage_exit(void) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "Syncing coverage data.\n"); +#endif + __gcov_flush(); +} + + diff --git a/src/lib/gcov-io.c b/src/lib/gcov-io.c new file mode 100644 index 0000000..d2fee03 --- /dev/null +++ b/src/lib/gcov-io.c @@ -0,0 +1,556 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007, + 2008 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Routines declared in gcov-io.h. This file should be #included by + another source file, after having #included gcov-io.h. */ + +#ifdef __COREBOOT__ + +#endif + +#if !IN_GCOV +static void gcov_write_block (unsigned); +static gcov_unsigned_t *gcov_write_words (unsigned); +#endif +static const gcov_unsigned_t *gcov_read_words (unsigned); +#if !IN_LIBGCOV +static void gcov_allocate (unsigned); +#endif + +static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +{ +#if !IN_LIBGCOV + if (gcov_var.endian) + { + value = (value >> 16) | (value << 16); + value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); + } +#endif + return value; +} + +/* Open a gcov file. NAME is the name of the file to open and MODE + indicates whether a new file should be created, or an existing file + opened. If MODE is >= 0 an existing file will be opened, if + possible, and if MODE is <= 0, a new file will be created. Use + MODE=0 to attempt to reopen an existing file and then fall back on + creating a new one. If MODE < 0, the file will be opened in + read-only mode. Otherwise it will be opened for modification. + Return zero on failure, >0 on opening an existing file and <0 on + creating a new one. */ + +GCOV_LINKAGE int +#if IN_LIBGCOV +gcov_open (const char *name) +#else +gcov_open (const char *name, int mode) +#endif +{ +#if IN_LIBGCOV + const int mode = 0; +#endif +#if GCOV_LOCKED + struct flock s_flock; + int fd; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif + + gcc_assert (!gcov_var.file); + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; +#if !IN_LIBGCOV + gcov_var.endian = 0; +#endif +#if GCOV_LOCKED + if (mode > 0) + { + /* Read-only mode - acquire a read-lock. */ + s_flock.l_type = F_RDLCK; + fd = open (name, O_RDONLY); + } + else + { + /* Write mode - acquire a write-lock. */ + s_flock.l_type = F_WRLCK; + fd = open (name, O_RDWR | O_CREAT, 0666); + } + if (fd < 0) + return 0; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; + + gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); + + if (!gcov_var.file) + { + close (fd); + return 0; + } + + if (mode > 0) + gcov_var.mode = 1; + else if (mode == 0) + { + struct stat st; + + if (fstat (fd, &st) < 0) + { + fclose (gcov_var.file); + gcov_var.file = 0; + return 0; + } + if (st.st_size != 0) + gcov_var.mode = 1; + else + gcov_var.mode = mode * 2 + 1; + } + else + gcov_var.mode = mode * 2 + 1; +#else + if (mode >= 0) + gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + + if (gcov_var.file) + gcov_var.mode = 1; + else if (mode <= 0) + { + gcov_var.file = fopen (name, "w+b"); + if (gcov_var.file) + gcov_var.mode = mode * 2 + 1; + } + if (!gcov_var.file) + return 0; +#endif + + setbuf (gcov_var.file, (char *)0); + + return 1; +} + +/* Close the current gcov file. Flushes data to disk. Returns nonzero + on failure or error flag set. */ + +GCOV_LINKAGE int +gcov_close (void) +{ + if (gcov_var.file) + { +#if !IN_GCOV + if (gcov_var.offset && gcov_var.mode < 0) + gcov_write_block (gcov_var.offset); +#endif + fclose (gcov_var.file); + gcov_var.file = 0; + gcov_var.length = 0; + } +#if !IN_LIBGCOV + free (gcov_var.buffer); + gcov_var.alloc = 0; + gcov_var.buffer = 0; +#endif + gcov_var.mode = 0; + return gcov_var.error; +} + +#if !IN_LIBGCOV +/* Check if MAGIC is EXPECTED. Use it to determine endianness of the + file. Returns +1 for same endian, -1 for other endian and zero for + not EXPECTED. */ + +GCOV_LINKAGE int +gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) +{ + if (magic == expected) + return 1; + magic = (magic >> 16) | (magic << 16); + magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); + if (magic == expected) + { + gcov_var.endian = 1; + return -1; + } + return 0; +} +#endif + +#if !IN_LIBGCOV +static void +gcov_allocate (unsigned length) +{ + size_t new_size = gcov_var.alloc; + + if (!new_size) + new_size = GCOV_BLOCK_SIZE; + new_size += length; + new_size *= 2; + + gcov_var.alloc = new_size; + gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); +} +#endif + +#if !IN_GCOV +/* Write out the current block, if needs be. */ + +static void +gcov_write_block (unsigned size) +{ + if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + gcov_var.error = 1; + gcov_var.start += size; + gcov_var.offset -= size; +} + +/* Allocate space to write BYTES bytes to the gcov file. Return a + pointer to those bytes, or NULL on failure. */ + +static gcov_unsigned_t * +gcov_write_words (unsigned words) +{ + gcov_unsigned_t *result; + + gcc_assert (gcov_var.mode < 0); +#if IN_LIBGCOV + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + { + gcov_write_block (GCOV_BLOCK_SIZE); + if (gcov_var.offset) + { + gcc_assert (gcov_var.offset == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); + } + } +#else + if (gcov_var.offset + words > gcov_var.alloc) + gcov_allocate (gcov_var.offset + words); +#endif + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + + return result; +} + +/* Write unsigned VALUE to coverage file. Sets error flag + appropriately. */ + +GCOV_LINKAGE void +gcov_write_unsigned (gcov_unsigned_t value) +{ + gcov_unsigned_t *buffer = gcov_write_words (1); + + buffer[0] = value; +} + +/* Write counter VALUE to coverage file. Sets error flag + appropriately. */ + +#if IN_LIBGCOV +GCOV_LINKAGE void +gcov_write_counter (gcov_type value) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = (gcov_unsigned_t) value; + if (sizeof (value) > sizeof (gcov_unsigned_t)) + buffer[1] = (gcov_unsigned_t) (value >> 32); + else + buffer[1] = 0; +} +#endif /* IN_LIBGCOV */ + +#if !IN_LIBGCOV +/* Write STRING to coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE void +gcov_write_string (const char *string) +{ + unsigned length = 0; + unsigned alloc = 0; + gcov_unsigned_t *buffer; + + if (string) + { + length = strlen (string); + alloc = (length + 4) >> 2; + } + + buffer = gcov_write_words (1 + alloc); + + buffer[0] = alloc; + buffer[alloc] = 0; + memcpy (&buffer[1], string, length); +} +#endif + +#if !IN_LIBGCOV +/* Write a tag TAG and reserve space for the record length. Return a + value to be used for gcov_write_length. */ + +GCOV_LINKAGE gcov_position_t +gcov_write_tag (gcov_unsigned_t tag) +{ + gcov_position_t result = gcov_var.start + gcov_var.offset; + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = 0; + + return result; +} + +/* Write a record length using POSITION, which was returned by + gcov_write_tag. The current file position is the end of the + record, and is restored before returning. Returns nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_length (gcov_position_t position) +{ + unsigned offset; + gcov_unsigned_t length; + gcov_unsigned_t *buffer; + + gcc_assert (gcov_var.mode < 0); + gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); + gcc_assert (position >= gcov_var.start); + offset = position - gcov_var.start; + length = gcov_var.offset - offset - 2; + buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; + buffer[1] = length; + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + gcov_write_block (gcov_var.offset); +} + +#else /* IN_LIBGCOV */ + +/* Write a tag TAG and length LENGTH. */ + +GCOV_LINKAGE void +gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = length; +} + +/* Write a summary structure to the gcov file. Return nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) +{ + unsigned ix; + const struct gcov_ctr_summary *csum; + + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); + gcov_write_unsigned (summary->checksum); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + gcov_write_unsigned (csum->num); + gcov_write_unsigned (csum->runs); + gcov_write_counter (csum->sum_all); + gcov_write_counter (csum->run_max); + gcov_write_counter (csum->sum_max); + } +} +#endif /* IN_LIBGCOV */ + +#endif /*!IN_GCOV */ + +/* Return a pointer to read BYTES bytes from the gcov file. Returns + NULL on failure (read past EOF). */ + +static const gcov_unsigned_t * +gcov_read_words (unsigned words) +{ + const gcov_unsigned_t *result; + unsigned excess = gcov_var.length - gcov_var.offset; + + gcc_assert (gcov_var.mode > 0); + if (excess < words) + { + gcov_var.start += gcov_var.offset; +#if IN_LIBGCOV + if (excess) + { + gcc_assert (excess == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); + } +#else + memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); +#endif + gcov_var.offset = 0; + gcov_var.length = excess; +#if IN_LIBGCOV + gcc_assert (!gcov_var.length || gcov_var.length == 1); + excess = GCOV_BLOCK_SIZE; +#else + if (gcov_var.length + words > gcov_var.alloc) + gcov_allocate (gcov_var.length + words); + excess = gcov_var.alloc - gcov_var.length; +#endif + excess = fread (gcov_var.buffer + gcov_var.length, + 1, excess << 2, gcov_var.file) >> 2; + gcov_var.length += excess; + if (gcov_var.length < words) + { + gcov_var.overread += words - gcov_var.length; + gcov_var.length = 0; + return 0; + } + } + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + return result; +} + +/* Read unsigned value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_unsigned (void) +{ + gcov_unsigned_t value; + const gcov_unsigned_t *buffer = gcov_read_words (1); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + return value; +} + +/* Read counter value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_type +gcov_read_counter (void) +{ + gcov_type value; + const gcov_unsigned_t *buffer = gcov_read_words (2); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + if (sizeof (value) > sizeof (gcov_unsigned_t)) + value |= ((gcov_type) from_file (buffer[1])) << 32; + else if (buffer[1]) + gcov_var.error = -1; + + return value; +} + +/* Read string from coverage file. Returns a pointer to a static + buffer, or NULL on empty string. You must copy the string before + calling another gcov function. */ + +#if !IN_LIBGCOV +GCOV_LINKAGE const char * +gcov_read_string (void) +{ + unsigned length = gcov_read_unsigned (); + + if (!length) + return 0; + + return (const char *) gcov_read_words (length); +} +#endif + +GCOV_LINKAGE void +gcov_read_summary (struct gcov_summary *summary) +{ + unsigned ix; + struct gcov_ctr_summary *csum; + + summary->checksum = gcov_read_unsigned (); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + csum->num = gcov_read_unsigned (); + csum->runs = gcov_read_unsigned (); + csum->sum_all = gcov_read_counter (); + csum->run_max = gcov_read_counter (); + csum->sum_max = gcov_read_counter (); + } +} + +#if !IN_LIBGCOV +/* Reset to a known position. BASE should have been obtained from + gcov_position, LENGTH should be a record length. */ + +GCOV_LINKAGE void +gcov_sync (gcov_position_t base, gcov_unsigned_t length) +{ + gcc_assert (gcov_var.mode > 0); + base += length; + if (base - gcov_var.start <= gcov_var.length) + gcov_var.offset = base - gcov_var.start; + else + { + gcov_var.offset = gcov_var.length = 0; + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; + } +} +#endif + +#if IN_LIBGCOV +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + gcc_assert (gcov_var.mode < 0); + if (gcov_var.offset) + gcov_write_block (gcov_var.offset); + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; +} +#endif + +#if IN_GCOV > 0 +/* Return the modification time of the current gcov file. */ + +GCOV_LINKAGE time_t +gcov_time (void) +{ + struct stat status; + + if (fstat (fileno (gcov_var.file), &status)) + return 0; + else + return status.st_mtime; +} +#endif /* IN_GCOV */ diff --git a/src/lib/gcov-io.h b/src/lib/gcov-io.h new file mode 100644 index 0000000..4502bd6 --- /dev/null +++ b/src/lib/gcov-io.h @@ -0,0 +1,639 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, + 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + + +/* Coverage information is held in two files. A notes file, which is + generated by the compiler, and a data file, which is generated by + the program under test. Both files use a similar structure. We do + not attempt to make these files backwards compatible with previous + versions, as you only need coverage information when developing a + program. We do hold version information, so that mismatches can be + detected, and we use a format that allows tools to skip information + they do not understand or are not interested in. + + Numbers are recorded in the 32 bit unsigned binary form of the + endianness of the machine generating the file. 64 bit numbers are + stored as two 32 bit numbers, the low part first. Strings are + padded with 1 to 4 NUL bytes, to bring the length up to a multiple + of 4. The number of 4 bytes is stored, followed by the padded + string. Zero length and NULL strings are simply stored as a length + of zero (they have no trailing NUL or padding). + + int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3 + int64: int32:low int32:high + string: int32:0 | int32:length char* char:0 padding + padding: | char:0 | char:0 char:0 | char:0 char:0 char:0 + item: int32 | int64 | string + + The basic format of the files is + + file : int32:magic int32:version int32:stamp record* + + The magic ident is different for the notes and the data files. The + magic ident is used to determine the endianness of the file, when + reading. The version is the same for both files and is derived + from gcc's version number. The stamp value is used to synchronize + note and data files and to synchronize merging within a data + file. It need not be an absolute time stamp, merely a ticker that + increments fast enough and cycles slow enough to distinguish + different compile/run/compile cycles. + + Although the ident and version are formally 32 bit numbers, they + are derived from 4 character ASCII strings. The version number + consists of the single character major version number, a two + character minor version number (leading zero for versions less than + 10), and a single character indicating the status of the release. + That will be 'e' experimental, 'p' prerelease and 'r' for release. + Because, by good fortune, these are in alphabetical order, string + collating can be used to compare version strings. Be aware that + the 'e' designation will (naturally) be unstable and might be + incompatible with itself. For gcc 3.4 experimental, it would be + '304e' (0x33303465). When the major version reaches 10, the + letters A-Z will be used. Assuming minor increments releases every + 6 months, we have to make a major increment every 50 years. + Assuming major increments releases every 5 years, we're ok for the + next 155 years -- good enough for me. + + A record has a tag, length and variable amount of data. + + record: header data + header: int32:tag int32:length + data: item* + + Records are not nested, but there is a record hierarchy. Tag + numbers reflect this hierarchy. Tags are unique across note and + data files. Some record types have a varying amount of data. The + LENGTH is the number of 4bytes that follow and is usually used to + determine how much data. The tag value is split into 4 8-bit + fields, one for each of four possible levels. The most significant + is allocated first. Unused levels are zero. Active levels are + odd-valued, so that the LSB of the level is one. A sub-level + incorporates the values of its superlevels. This formatting allows + you to determine the tag hierarchy, without understanding the tags + themselves, and is similar to the standard section numbering used + in technical documents. Level values [1..3f] are used for common + tags, values [41..9f] for the notes file and [a1..ff] for the data + file. + + The basic block graph file contains the following records + note: unit function-graph* + unit: header int32:checksum string:source + function-graph: announce_function basic_blocks {arcs | lines}* + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + string:name string:source int32:lineno + basic_block: header int32:flags* + arcs: header int32:block_no arc* + arc: int32:dest_block int32:flags + lines: header int32:block_no line* + int32:0 string:NULL + line: int32:line_no | int32:0 string:filename + + The BASIC_BLOCK record holds per-bb flags. The number of blocks + can be inferred from its data length. There is one ARCS record per + basic block. The number of arcs from a bb is implicit from the + data length. It enumerates the destination bb and per-arc flags. + There is one LINES record per basic block, it enumerates the source + lines which belong to that basic block. Source file names are + introduced by a line number of 0, following lines are from the new + source file. The initial source file for the function is NULL, but + the current source file should be remembered from one LINES record + to the next. The end of a block is indicated by an empty filename + - this does not reset the current source file. Note there is no + ordering of the ARCS and LINES records: they may be in any order, + interleaved in any manner. The current filename follows the order + the LINES records are stored in the file, *not* the ordering of the + blocks they are for. + + The data file contains the following records. + data: {unit summary:object summary:program* function-data*}* + unit: header int32:checksum + function-data: announce_function present counts + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + present: header int32:present + counts: header int64:count* + summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE + count-summary: int32:num int32:runs int64:sum + int64:max int64:sum_max + + The ANNOUNCE_FUNCTION record is the same as that in the note file, + but without the source location. The COUNTS gives the + counter values for instrumented features. The about the whole + program. The checksum is used for whole program summaries, and + disambiguates different programs which include the same + instrumented object file. There may be several program summaries, + each with a unique checksum. The object summary's checksum is + zero. Note that the data file might contain information from + several runs concatenated, or the data might be merged. + + This file is included by both the compiler, gcov tools and the + runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to + distinguish which case is which. If IN_LIBGCOV is nonzero, + libgcov is being built. If IN_GCOV is nonzero, the gcov tools are + being built. Otherwise the compiler is being built. IN_GCOV may be + positive or negative. If positive, we are compiling a tool that + requires additional functions (see the code for knowledge of what + those functions are). */ + +#ifndef GCC_GCOV_IO_H +#define GCC_GCOV_IO_H + +#ifdef __COREBOOT__ +#define GCOV_LINKAGE /* nothing */ +/* We need the definitions for + BITS_PER_UNIT and + LONG_LONG_TYPE_SIZE + They are defined in gcc/defaults.h and gcc/config/ + (like, gcc/config/i386/i386.h). And it can be overridden by setting + in build scripts. Here I hardcoded the value for x86. */ +#define BITS_PER_UNIT 8 +#define LONG_LONG_TYPE_SIZE 64 + +/* There are many gcc_assertions. Set the vaule to 1 if we want a warning + message if the assertion fails. */ +#ifndef ENABLE_ASSERT_CHECKING +#define ENABLE_ASSERT_CHECKING 1 +#endif +#endif /* __COREBOOT__ */ + +#if IN_LIBGCOV +/* About the target */ + +#if BITS_PER_UNIT == 8 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef unsigned gcov_position_t __attribute__ ((mode (SI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (DI))); +#else +typedef signed gcov_type __attribute__ ((mode (SI))); +#endif +#else +#if BITS_PER_UNIT == 16 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); +typedef unsigned gcov_position_t __attribute__ ((mode (HI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (SI))); +#else +typedef signed gcov_type __attribute__ ((mode (HI))); +#endif +#else +typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); +typedef unsigned gcov_position_t __attribute__ ((mode (QI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (HI))); +#else +typedef signed gcov_type __attribute__ ((mode (QI))); +#endif +#endif +#endif + + +#if defined (TARGET_POSIX_IO) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#else /* !IN_LIBGCOV */ +/* About the host */ + +typedef unsigned gcov_unsigned_t; +typedef unsigned gcov_position_t; +/* gcov_type is typedef'd elsewhere for the compiler */ +#if IN_GCOV +#define GCOV_LINKAGE static +typedef HOST_WIDEST_INT gcov_type; +#if IN_GCOV > 0 +#include +#endif +#else /*!IN_GCOV */ +#define GCOV_TYPE_SIZE (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32) +#endif + +#if defined (HOST_HAS_F_SETLKW) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#endif /* !IN_LIBGCOV */ + +/* In gcov we want function linkage to be static. In the compiler we want + it extern, so that they can be accessed from elsewhere. In libgcov we + need these functions to be extern, so prefix them with __gcov. In + libgcov they must also be hidden so that the instance in the executable + is not also used in a DSO. */ +#if IN_LIBGCOV + +#ifndef __COREBOOT__ +#include "tconfig.h" +#endif /* __COREBOOT__ */ + +#define gcov_var __gcov_var +#define gcov_open __gcov_open +#define gcov_close __gcov_close +#define gcov_write_tag_length __gcov_write_tag_length +#define gcov_position __gcov_position +#define gcov_seek __gcov_seek +#define gcov_rewrite __gcov_rewrite +#define gcov_is_error __gcov_is_error +#define gcov_write_unsigned __gcov_write_unsigned +#define gcov_write_counter __gcov_write_counter +#define gcov_write_summary __gcov_write_summary +#define gcov_read_unsigned __gcov_read_unsigned +#define gcov_read_counter __gcov_read_counter +#define gcov_read_summary __gcov_read_summary + +/* Poison these, so they don't accidentally slip in. */ +#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length +#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#else + +#define ATTRIBUTE_HIDDEN + +#endif + +#ifndef GCOV_LINKAGE +#define GCOV_LINKAGE extern +#endif + +/* File suffixes. */ +#define GCOV_DATA_SUFFIX ".gcda" +#define GCOV_NOTE_SUFFIX ".gcno" + +/* File magic. Must not be palindromes. */ +#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ +#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */ + +/* gcov-iov.h is automatically generated by the makefile from + version.c, it looks like + #define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef) +*/ +#include "gcov-iov.h" + +/* Convert a magic or version number to a 4 character string. */ +#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ + ((ARRAY)[0] = (char)((VALUE) >> 24), \ + (ARRAY)[1] = (char)((VALUE) >> 16), \ + (ARRAY)[2] = (char)((VALUE) >> 8), \ + (ARRAY)[3] = (char)((VALUE) >> 0)) + +/* The record tags. Values [1..3f] are for tags which may be in either + file. Values [41..9f] for those in the note file and [a1..ff] for + the data file. The tag value zero is used as an explicit end of + file marker -- it is not required to be present. */ + +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) +#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) +#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) +#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) +#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_SUMMARY_LENGTH \ + (1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2)) + +/* Counters that are collected. */ +#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ +#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be + summaried. */ +#define GCOV_FIRST_VALUE_COUNTER 1 /* The first of counters used for value + profiling. They must form a consecutive + interval and their order must match + the order of HIST_TYPEs in + value-prof.h. */ +#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */ +#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm + of a value. */ +#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */ +#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between + consecutive values of expression. */ + +#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */ +#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the + counter. */ +#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to + counter. */ +#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value + profiling. */ +#define GCOV_COUNTERS 8 + +/* Number of counters used for value profiling. */ +#define GCOV_N_VALUE_COUNTERS \ + (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) + + /* A list of human readable names of the counters */ +#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \ + "delta", "indirect_call", "average", "ior"} + + /* Names of merge functions for counters. */ +#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_single", \ + "__gcov_merge_delta", \ + "__gcov_merge_single", \ + "__gcov_merge_add", \ + "__gcov_merge_ior"} + +/* Convert a counter index to a tag. */ +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) +/* Convert a tag to a counter. */ +#define GCOV_COUNTER_FOR_TAG(TAG) \ + ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)) +/* Check whether a tag is a counter tag. */ +#define GCOV_TAG_IS_COUNTER(TAG) \ + (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) + +/* The tag level mask has 1's in the position of the inner levels, & + the lsb of the current level, and zero on the current and outer + levels. */ +#define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG)) + +/* Return nonzero if SUB is an immediate subtag of TAG. */ +#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \ + && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG))) + +/* Return nonzero if SUB is at a sublevel to TAG. */ +#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB)) + +/* Basic block flags. */ +#define GCOV_BLOCK_UNEXPECTED (1 << 1) + +/* Arc flags. */ +#define GCOV_ARC_ON_TREE (1 << 0) +#define GCOV_ARC_FAKE (1 << 1) +#define GCOV_ARC_FALLTHROUGH (1 << 2) + +/* Structured records. */ + +/* Cumulative counter data. */ +struct gcov_ctr_summary +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_unsigned_t runs; /* number of program runs */ + gcov_type sum_all; /* sum of all counters accumulated. */ + gcov_type run_max; /* maximum value on a single run. */ + gcov_type sum_max; /* sum of individual run max values. */ +}; + +/* Object & program summary record. */ +struct gcov_summary +{ + gcov_unsigned_t checksum; /* checksum of program */ + struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; +}; + +/* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ + +#if IN_LIBGCOV +/* Information about counters for a single function. */ +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ +}; + +/* Information about a single function. This uses the trailing array + idiom. The number of counters is determined from the merge pointer + array in gcov_info. The key is used to detect which of a set of + comdat functions was selected -- it points to the gcov_info object + of the object file containing the selected comdat function. */ + +struct gcov_fn_info +{ + const struct gcov_info *key; /* comdat key */ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ + gcov_unsigned_t cfg_checksum; /* function cfg checksum */ + struct gcov_ctr_info ctrs[0]; /* instrumented counters */ +}; + +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; /* output file name */ + + gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for + unused) */ + + unsigned n_functions; /* number of functions */ + const struct gcov_fn_info *const *functions; /* pointer to pointers + to function information */ +}; + +/* Register a new object file module. */ +extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + +#ifndef __COREBOOT__ +/* Called before fork, to avoid double counting. */ +extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; +#endif + +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common value. */ +extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common difference between + consecutive values. */ +extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function that just ors the counters together. */ +extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The profiler functions. */ +extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); +extern void __gcov_pow2_profiler (gcov_type *, gcov_type); +extern void __gcov_one_value_profiler (gcov_type *, gcov_type); +extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *); +extern void __gcov_average_profiler (gcov_type *, gcov_type); +extern void __gcov_ior_profiler (gcov_type *, gcov_type); + +#ifndef inhibit_libc +/* The wrappers around some library functions.. */ +extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; +extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execve (const char *, char *const [], char *const []) + ATTRIBUTE_HIDDEN; +#endif + +#endif /* IN_LIBGCOV */ + +#if IN_LIBGCOV >= 0 + +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var ATTRIBUTE_HIDDEN; + +/* Functions for reading and writing gcov files. In libgcov you can + open the file for reading then writing. Elsewhere you can open the + file either for reading or for writing. When reading a file you may + use the gcov_read_* functions, gcov_sync, gcov_position, & + gcov_error. When writing a file you may use the gcov_write + functions, gcov_seek & gcov_error. When a file is to be rewritten + you use the functions for reading, then gcov_rewrite then the + functions for writing. Your file may become corrupted if you break + these invariants. */ +#if IN_LIBGCOV +GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; +#else +GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); +GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); +#endif +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; + +/* Available everywhere. */ +static gcov_position_t gcov_position (void); +static int gcov_is_error (void); + +GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; + +#if IN_LIBGCOV +/* Available only in libgcov */ +GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, + const struct gcov_summary *) + ATTRIBUTE_HIDDEN; +static void gcov_rewrite (void); +GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; +#else +/* Available outside libgcov */ +GCOV_LINKAGE const char *gcov_read_string (void); +GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, + gcov_unsigned_t /*length */); +#endif + +#if !IN_GCOV +/* Available outside gcov */ +GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +#endif + +#if !IN_GCOV && !IN_LIBGCOV +/* Available only in compiler */ +GCOV_LINKAGE void gcov_write_string (const char *); +GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); +GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); +#endif + +#if IN_GCOV > 0 +/* Available in gcov */ +GCOV_LINKAGE time_t gcov_time (void); +#endif + +/* Save the current position in the gcov file. */ + +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ + +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ + +static inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + +#endif /* IN_LIBGCOV >= 0 */ + +#endif /* GCC_GCOV_IO_H */ diff --git a/src/lib/gcov-iov.h b/src/lib/gcov-iov.h new file mode 100644 index 0000000..09951fb --- /dev/null +++ b/src/lib/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `4.7.2 (4 7) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3430372a) /* 407* */ diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 206e82b..eed243a 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -42,6 +42,7 @@ it with the version available from LANL. #if CONFIG_WRITE_HIGH_TABLES #include #endif +#include #include /** @@ -62,6 +63,10 @@ void hardwaremain(int boot_complete) timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); +#if CONFIG_COVERAGE + coverage_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); diff --git a/src/lib/libgcov.c b/src/lib/libgcov.c new file mode 100644 index 0000000..a32ce55 --- /dev/null +++ b/src/lib/libgcov.c @@ -0,0 +1,1158 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define __COREBOOT__ +#ifdef __COREBOOT__ +#include +#include +#include +#include +typedef s32 pid_t; +#define gcc_assert(x) ASSERT(x) +#define fprintf(file, x...) printk(BIOS_ERR, x) +#define alloca(size) __builtin_alloca (size) +#include "gcov-glue.c" + +/* Define MACROs to be used by coreboot compilation. */ +# define L_gcov +# define L_gcov_interval_profiler +# define L_gcov_pow2_profiler +# define L_gcov_one_value_profiler +# define L_gcov_indirect_call_profiler +# define L_gcov_average_profiler +# define L_gcov_ior_profiler + +# define HAVE_CC_TLS 0 +# define __GCOV_KERNEL__ + +# define IN_LIBGCOV 1 +# define IN_GCOV 0 +#else /* __COREBOOT__ */ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#endif /* __COREBOOT__ */ + +#ifndef __COREBOOT__ +#if defined(inhibit_libc) +#define IN_LIBGCOV (-1) +#else +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include +#define IN_LIBGCOV 1 +#if defined(L_gcov) +#define GCOV_LINKAGE /* nothing */ +#endif +#endif +#endif /* __COREBOOT__ */ +#include "gcov-io.h" + +#if defined(inhibit_libc) +/* If libc and its header files are not available, provide dummy functions. */ + +#ifdef L_gcov +void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} +void __gcov_flush (void) {} +#endif + +#ifdef L_gcov_merge_add +void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_single +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_delta +void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#else + +#ifndef __COREBOOT__ +#include +#if GCOV_LOCKED +#include +#include +#include +#endif +#else +void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif /* __COREBOOT__ */ + +#ifdef L_gcov +#include "gcov-io.c" + +struct gcov_fn_buffer +{ + struct gcov_fn_buffer *next; + unsigned fn_ix; + struct gcov_fn_info info; + /* note gcov_fn_info ends in a trailing array. */ +}; + +/* Chain of per-object gcov structures. */ +static struct gcov_info *gcov_list; + +/* Size of the longest file name. */ +static size_t gcov_max_filename = 0; + +/* Make sure path component of the given FILENAME exists, create + missing directories. FILENAME must be writable. + Returns zero on success, or -1 if an error occurred. */ + +static int +create_file_directory (char *filename) +{ +#ifdef __COREBOOT__ + (void) filename; + return 0; +#else +#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +#else + char *s; + + s = filename; + + if (HAS_DRIVE_SPEC(s)) + s += 2; + if (IS_DIR_SEPARATOR(*s)) + ++s; + for (; *s != '\0'; s++) + if (IS_DIR_SEPARATOR(*s)) + { + char sep = *s; + *s = '\0'; + + /* Try to make directory if it doesn't already exist. */ + if (access (filename, F_OK) == -1 +#ifdef TARGET_POSIX_IO + && mkdir (filename, 0755) == -1 +#else + && mkdir (filename) == -1 +#endif + /* The directory might have been made by another process. */ + && errno != EEXIST) + { + fprintf (stderr, "profiling:%s:Cannot create directory\n", + filename); + *s = sep; + return -1; + }; + + *s = sep; + }; + return 0; +#endif +#endif +} + +static struct gcov_fn_buffer * +free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, + unsigned limit) +{ + struct gcov_fn_buffer *next; + unsigned ix, n_ctr = 0; + + if (!buffer) + return 0; + next = buffer->next; + + for (ix = 0; ix != limit; ix++) + if (gi_ptr->merge[ix]) + free (buffer->info.ctrs[n_ctr++].values); + free (buffer); + return next; +} + +static struct gcov_fn_buffer ** +buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, + struct gcov_fn_buffer **end_ptr, unsigned fn_ix) +{ + unsigned n_ctrs = 0, ix = 0; + struct gcov_fn_buffer *fn_buffer; + unsigned len; + + for (ix = GCOV_COUNTERS; ix--;) + if (gi_ptr->merge[ix]) + n_ctrs++; + + len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; + fn_buffer = (struct gcov_fn_buffer *)malloc (len); + + if (!fn_buffer) + goto fail; + + fn_buffer->next = 0; + fn_buffer->fn_ix = fn_ix; + fn_buffer->info.ident = gcov_read_unsigned (); + fn_buffer->info.lineno_checksum = gcov_read_unsigned (); + fn_buffer->info.cfg_checksum = gcov_read_unsigned (); + + for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) + { + gcov_unsigned_t length; + gcov_type *values; + + if (!gi_ptr->merge[ix]) + continue; + + if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) + { + len = 0; + goto fail; + } + + length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); + len = length * sizeof (gcov_type); + values = (gcov_type *)malloc (len); + if (!values) + goto fail; + + fn_buffer->info.ctrs[n_ctrs].num = length; + fn_buffer->info.ctrs[n_ctrs].values = values; + + while (length--) + *values++ = gcov_read_counter (); + n_ctrs++; + } + + *end_ptr = fn_buffer; + return &fn_buffer->next; + +fail: + fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix, + len ? "cannot allocate" : "counter mismatch", len ? len : ix); + + return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); +} + +/* Add an unsigned value to the current crc */ + +static gcov_unsigned_t +crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) +{ + unsigned ix; + + for (ix = 32; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; + crc32 <<= 1; + crc32 ^= feedback; + } + + return crc32; +} + +/* Check if VERSION of the info block PTR matches libgcov one. + Return 1 on success, or zero in case of versions mismatch. + If FILENAME is not NULL, its value used for reporting purposes + instead of value from the info block. */ + +static int +gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, + const char *filename) +{ + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fprintf (stderr, + "profiling:%s:Version mismatch - expected %.4s got %.4s\n", + filename? filename : ptr->filename, e, v); + return 0; + } + return 1; +} + +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. We use this + program's checksum to make sure we only accumulate whole program + statistics to the correct summary. An object file might be embedded + in two separate programs, and we must keep the two program + summaries separate. */ + +static void +gcov_exit (void) +{ + struct gcov_info *gi_ptr; + const struct gcov_fn_info *gfi_ptr; + struct gcov_summary this_prg; /* summary for program. */ + struct gcov_summary all_prg; /* summary for all instances of program. */ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; + int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; + size_t prefix_length; + char *gi_filename, *gi_filename_up; + gcov_unsigned_t crc32 = 0; + + memset (&all_prg, 0, sizeof (all_prg)); + /* Find the totals for this execution. */ + memset (&this_prg, 0, sizeof (this_prg)); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); + crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); + + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (gfi_ptr && gfi_ptr->key != gi_ptr) + gfi_ptr = 0; + + crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); + crc32 = crc32_unsigned (crc32, + gfi_ptr ? gfi_ptr->lineno_checksum : 0); + if (!gfi_ptr) + continue; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + cs_ptr = &this_prg.ctrs[t_ix]; + cs_ptr->num += ci_ptr->num; + crc32 = crc32_unsigned (crc32, ci_ptr->num); + + for (c_num = 0; c_num < ci_ptr->num; c_num++) + { + cs_ptr->sum_all += ci_ptr->values[c_num]; + if (cs_ptr->run_max < ci_ptr->values[c_num]) + cs_ptr->run_max = ci_ptr->values[c_num]; + } + ci_ptr++; + } + } + } + +#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); + if (tmp) + { + gcov_prefix_strip = atoi (tmp); + /* Do not consider negative values. */ + if (gcov_prefix_strip < 0) + gcov_prefix_strip = 0; + } + } + + /* Get file name relocation prefix. Non-absolute values are ignored. */ + gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix) + { + prefix_length = strlen(gcov_prefix); + + /* Remove an unnecessary trailing '/' */ + if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; + } + else +#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume + relative. */ + if (gcov_prefix_strip != 0 && prefix_length == 0) + { + gcov_prefix = "."; + prefix_length = 1; + } + /* Allocate and initialize the filename scratch space plus one. */ + gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); + if (prefix_length) + memcpy (gi_filename, gcov_prefix, prefix_length); + gi_filename_up = gi_filename + prefix_length; + + /* Now merge each file. */ + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned n_counts; + struct gcov_summary prg; /* summary for this object over all + program. */ + struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all; + int error = 0; + gcov_unsigned_t tag, length; + gcov_position_t summary_pos = 0; + gcov_position_t eof_pos = 0; + const char *fname, *s; + struct gcov_fn_buffer *fn_buffer = 0; + struct gcov_fn_buffer **fn_tail = &fn_buffer; + + fname = gi_ptr->filename; + + /* Avoid to add multiple drive letters into combined path. */ + if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) + fname += 2; + + /* Build relocated filename, stripping off leading + directories from the initial filename if requested. */ + if (gcov_prefix_strip > 0) + { + int level = 0; + s = fname; + if (IS_DIR_SEPARATOR(*s)) + ++s; + + /* Skip selected directory levels. */ + for (; (*s != '\0') && (level < gcov_prefix_strip); s++) + if (IS_DIR_SEPARATOR(*s)) + { + fname = s; + level++; + } + } + + /* Update complete filename with stripped original. */ + if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + { + /* If prefix is given, add directory separator. */ + strcpy (gi_filename_up, "/"); + strcpy (gi_filename_up + 1, fname); + } + else + strcpy (gi_filename_up, fname); + + if (!gcov_open (gi_filename)) + { + /* Open failed likely due to missed directory. + Create directory and retry to open file. */ + if (create_file_directory (gi_filename)) + { + fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + continue; + } + if (!gcov_open (gi_filename)) + { + fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + continue; + } + } + + tag = gcov_read_unsigned (); + if (tag) + { + /* Merge data from file. */ + if (tag != GCOV_DATA_MAGIC) + { + fprintf (stderr, "profiling:%s:Not a gcov data file\n", + gi_filename); + goto read_fatal; + } + length = gcov_read_unsigned (); + if (!gcov_version (gi_ptr, length, gi_filename)) + goto read_fatal; + + length = gcov_read_unsigned (); + if (length != gi_ptr->stamp) + /* Read from a different compilation. Overwrite the file. */ + goto rewrite; + + /* Look for program summary. */ + for (f_ix = 0;;) + { + struct gcov_summary tmp; + + eof_pos = gcov_position (); + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_PROGRAM_SUMMARY) + break; + + f_ix--; + length = gcov_read_unsigned (); + if (length != GCOV_TAG_SUMMARY_LENGTH) + goto read_mismatch; + gcov_read_summary (&tmp); + if ((error = gcov_is_error ())) + goto read_error; + if (summary_pos || tmp.checksum != crc32) + goto next_summary; + + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num) + goto next_summary; + prg = tmp; + summary_pos = eof_pos; + + next_summary:; + } + + /* Merge execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; + f_ix++, tag = gcov_read_unsigned ()) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (tag != GCOV_TAG_FUNCTION) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (!length) + /* This function did not appear in the other program. + We have nothing to merge. */ + continue; + + if (length != GCOV_TAG_FUNCTION_LENGTH) + goto read_mismatch; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + { + /* This function appears in the other program. We + need to buffer the information in order to write + it back out -- we'll be inserting data before + this point, so cannot simply keep the data in the + file. */ + fn_tail = buffer_fn_data (gi_filename, + gi_ptr, fn_tail, f_ix); + if (!fn_tail) + goto read_mismatch; + continue; + } + + length = gcov_read_unsigned (); + if (length != gfi_ptr->ident) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->lineno_checksum) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->cfg_checksum) + goto read_mismatch; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + gcov_merge_fn merge = gi_ptr->merge[t_ix]; + + if (!merge) + continue; + + tag = gcov_read_unsigned (); + length = gcov_read_unsigned (); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) + goto read_mismatch; + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } + if ((error = gcov_is_error ())) + goto read_error; + } + + if (tag) + { + read_mismatch:; + fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n", + gi_filename, f_ix >= 0 ? "function" : "summary", + f_ix < 0 ? -1 - f_ix : f_ix); + goto read_fatal; + } + } + goto rewrite; + + read_error:; + fprintf (stderr, "profiling:%s:%s merging\n", gi_filename, + error < 0 ? "Overflow": "Error"); + + goto read_fatal; + + rewrite:; + gcov_rewrite (); + if (!summary_pos) + { + memset (&prg, 0, sizeof (prg)); + summary_pos = eof_pos; + } + + /* Merge the summaries. */ + for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) + { + cs_prg = &prg.ctrs[t_ix]; + cs_tprg = &this_prg.ctrs[t_ix]; + cs_all = &all_prg.ctrs[t_ix]; + + if (gi_ptr->merge[t_ix]) + { + if (!cs_prg->runs++) + cs_prg->num = cs_tprg->num; + cs_prg->sum_all += cs_tprg->sum_all; + if (cs_prg->run_max < cs_tprg->run_max) + cs_prg->run_max = cs_tprg->run_max; + cs_prg->sum_max += cs_tprg->run_max; + } + else if (cs_prg->runs) + goto read_mismatch; + + if (!cs_all->runs && cs_prg->runs) + memcpy (cs_all, cs_prg, sizeof (*cs_all)); + else if (!all_prg.checksum + && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) + && memcmp (cs_all, cs_prg, sizeof (*cs_all))) + { + fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n", + gi_filename, GCOV_LOCKED + ? "" : " or concurrently updated without locking support"); + all_prg.checksum = ~0u; + } + } + + prg.checksum = crc32; + + /* Write out the data. */ + if (!eof_pos) + { + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); + } + + if (summary_pos) + gcov_seek (summary_pos); + + /* Generate whole program statistics. */ + gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg); + + if (summary_pos < eof_pos) + gcov_seek (eof_pos); + + /* Write execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + unsigned buffered = 0; + + if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix) + { + /* Buffered data from another program. */ + buffered = 1; + gfi_ptr = &fn_buffer->info; + length = GCOV_TAG_FUNCTION_LENGTH; + } + else + { + gfi_ptr = gi_ptr->functions[f_ix]; + if (gfi_ptr && gfi_ptr->key == gi_ptr) + length = GCOV_TAG_FUNCTION_LENGTH; + else + length = 0; + } + + gcov_write_tag_length (GCOV_TAG_FUNCTION, length); + if (!length) + continue; + + gcov_write_unsigned (gfi_ptr->ident); + gcov_write_unsigned (gfi_ptr->lineno_checksum); + gcov_write_unsigned (gfi_ptr->cfg_checksum); + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + n_counts = ci_ptr->num; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + gcov_type *c_ptr = ci_ptr->values; + while (n_counts--) + gcov_write_counter (*c_ptr++); + ci_ptr++; + } + if (buffered) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + } + + gcov_write_unsigned (0); + + read_fatal:; + while (fn_buffer) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + + if ((error = gcov_close ())) + fprintf (stderr, error < 0 ? + "profiling:%s:Overflow writing\n" : + "profiling:%s:Error writing\n", + gi_filename); + } +} + +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + +void +__gcov_init (struct gcov_info *info) +{ + if (!info->version || !info->n_functions) + return; + if (gcov_version (info, info->version, 0)) + { + size_t filename_length = strlen(info->filename); + + /* Refresh the longest file name information */ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + +#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); +#endif + + info->next = gcov_list; + gcov_list = info; + } + info->version = 0; +} + +/* Called before fork or exec - write out profile information gathered so + far and reset it to zero. This avoids duplication or loss of the + profile information gathered so far. */ + +void +__gcov_flush (void) +{ + const struct gcov_info *gi_ptr; + + gcov_exit (); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + +#endif /* L_gcov */ + +#ifdef L_gcov_merge_add +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_add (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters += gcov_read_counter (); +} +#endif /* L_gcov_merge_add */ + +#ifdef L_gcov_merge_ior +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_ior (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters |= gcov_read_counter (); +} +#endif + +#ifdef L_gcov_merge_single +/* The profile merging function for choosing the most common value. + * It is given an array COUNTERS of N_COUNTERS old counters and it + * reads the same number of counters from the gcov file. The counters + * are split into 3-tuples where the members of the tuple have + * meanings: + * + * -- the stored candidate on the most common value of the measured entity + * -- counter + * -- total number of evaluations of the value + */ +void +__gcov_merge_single (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 3)); + n_measures = n_counters / 3; + for (i = 0; i < n_measures; i++, counters += 3) + { + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[0] == value) + counters[1] += counter; + else if (counter > counters[1]) + { + counters[0] = value; + counters[1] = counter - counters[1]; + } + else + counters[1] -= counter; + counters[2] += all; + } +} +#endif /* L_gcov_merge_single */ + +#ifdef L_gcov_merge_delta +/* The profile merging function for choosing the most common + difference between two consecutive evaluations of the value. It is + given an array COUNTERS of N_COUNTERS old counters and it reads the + same number of counters from the gcov file. The counters are split + into 4-tuples where the members of the tuple have meanings: + + -- the last value of the measured entity + -- the stored candidate on the most common difference + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_delta (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 4)); + n_measures = n_counters / 4; + for (i = 0; i < n_measures; i++, counters += 4) + { + /* last = */ gcov_read_counter (); + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[1] == value) + counters[2] += counter; + else if (counter > counters[2]) + { + counters[1] = value; + counters[2] = counter - counters[2]; + } + else + counters[2] -= counter; + counters[3] += all; + } +} +#endif /* L_gcov_merge_delta */ + +#ifdef L_gcov_interval_profiler +/* If VALUE is in interval , then increases the + corresponding counter in COUNTERS. If the VALUE is above or below + the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased + instead. */ + +void +__gcov_interval_profiler (gcov_type *counters, gcov_type value, + int start, unsigned steps) +{ + gcov_type delta = value - start; + if (delta < 0) + counters[steps + 1]++; + else if (delta >= steps) + counters[steps]++; + else + counters[delta]++; +} +#endif + +#ifdef L_gcov_pow2_profiler +/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise + COUNTERS[0] is incremented. */ + +void +__gcov_pow2_profiler (gcov_type *counters, gcov_type value) +{ + if (value & (value - 1)) + counters[0]++; + else + counters[1]++; +} +#endif + +/* Tries to determine the most common value among its inputs. Checks if the + value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] + is incremented. If this is not the case and COUNTERS[1] is not zero, + COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and + VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this + function is called more than 50% of the time with one value, this value + will be in COUNTERS[0] in the end. + + In any case, COUNTERS[2] is incremented. */ + +static inline void +__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) +{ + if (value == counters[0]) + counters[1]++; + else if (counters[1] == 0) + { + counters[1] = 1; + counters[0] = value; + } + else + counters[1]--; + counters[2]++; +} + +#ifdef L_gcov_one_value_profiler +void +__gcov_one_value_profiler (gcov_type *counters, gcov_type value) +{ + __gcov_one_value_profiler_body (counters, value); +} +#endif + +#ifdef L_gcov_indirect_call_profiler + +/* By default, the C++ compiler will use function addresses in the + vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero + tells the compiler to use function descriptors instead. The value + of this macro says how many words wide the descriptor is (normally 2), + but it may be dependent on target flags. Since we do not have access + to the target flags here we just check to see if it is set and use + that to set VTABLE_USES_DESCRIPTORS to 0 or 1. + + It is assumed that the address of a function descriptor may be treated + as a pointer to a function. */ + +#ifdef TARGET_VTABLE_USES_DESCRIPTORS +#define VTABLE_USES_DESCRIPTORS 1 +#else +#define VTABLE_USES_DESCRIPTORS 0 +#endif + +/* Tries to determine the most common value among its inputs. */ +void +__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, + void* cur_func, void* callee_func) +{ + /* If the C++ virtual tables contain function descriptors then one + function may have multiple descriptors and we need to dereference + the descriptors to see if they point to the same function. */ + if (cur_func == callee_func + || (VTABLE_USES_DESCRIPTORS && callee_func + && *(void **) cur_func == *(void **) callee_func)) + __gcov_one_value_profiler_body (counter, value); +} +#endif + + +#ifdef L_gcov_average_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_average_profiler (gcov_type *counters, gcov_type value) +{ + counters[0] += value; + counters[1] ++; +} +#endif + +#ifdef L_gcov_ior_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_ior_profiler (gcov_type *counters, gcov_type value) +{ + *counters |= value; +} +#endif + +#ifdef L_gcov_fork +/* A wrapper for the fork function. Flushes the accumulated profiling data, so + that they are not counted twice. */ + +pid_t +__gcov_fork (void) +{ + __gcov_flush (); + return fork (); +} +#endif + +#ifdef L_gcov_execl +/* A wrapper for the execl function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execl (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execv (path, args); +} +#endif + +#ifdef L_gcov_execlp +/* A wrapper for the execlp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execlp (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execvp (path, args); +} +#endif + +#ifdef L_gcov_execle +/* A wrapper for the execle function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execle (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + char **envp; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + envp = va_arg (aq, char **); + va_end (aq); + + return execve (path, args, envp); +} +#endif + +#ifdef L_gcov_execv +/* A wrapper for the execv function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execv (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execv (path, argv); +} +#endif + +#ifdef L_gcov_execvp +/* A wrapper for the execvp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execvp (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execvp (path, argv); +} +#endif + +#ifdef L_gcov_execve +/* A wrapper for the execve function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execve (const char *path, char *const argv[], char *const envp[]) +{ + __gcov_flush (); + return execve (path, argv, envp); +} +#endif +#endif /* inhibit_libc */ diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 2556a14..c5fb62a 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -32,6 +32,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR @@ -518,6 +519,9 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) #if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); #endif +#if CONFIG_COVERAGE + coverage_exit(); +#endif /* Before we go off to run the payload, see if * we stayed within our bounds. From gerrit at coreboot.org Fri Jan 4 00:31:30 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Fri, 4 Jan 2013 00:31:30 +0100 Subject: [coreboot] Patch set updated for coreboot: 17b47dc update CFLAGS for armv7 References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2075 -gerrit commit 17b47dca27f6e7b9c1b63623b42f1a60eb41742c Author: David Hendricks Date: Thu Dec 27 13:30:55 2012 -0800 update CFLAGS for armv7 This updates $CFLAGS used for armv7. Most of them were just added to be consistent with what u-boot does. The important ones here are -march=armv7-a and -mthumb (to allow 16-bit Thumb instructions). I removed the hard float support because it got errors and coreboot should never use floats anyway. We're still having trouble with enums but I want to see how far it gets with this patch. Also, put the flags in a form that makes diffs easier to read. It's almost impossible otherwise. Finally, move some flags to the architecture Makefile, and rely on the fact that some are set for all architectures. Depends-On: I6f730d017391f9ec4401cdfd34931c869df10a9e Change-Id: Ia8a1ae22959933e06f7b996d1832cea40819f1ff Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/arch/armv7/Makefile.inc | 10 ++++++++++ util/xcompile/xcompile | 11 +++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 1a1271f..41145d9 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -138,6 +138,16 @@ endif ################################################################################ # done +CFLAGS += \ + -fno-common\ + -ffixed-r8\ + -mabi=aapcs-linux\ + -march=armv7-a\ + -marm\ + -mno-unaligned-access\ + -mthumb\ + -mthumb-interwork + # For various headers imported from Linux CFLAGS += -D__KERNEL__ CFLAGS += -D__LINUX_ARM_ARCH__=7 diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile index 4239176..ea975ec 100644 --- a/util/xcompile/xcompile +++ b/util/xcompile/xcompile @@ -106,14 +106,9 @@ detect_special_flags() { CFLAGS="$CFLAGS -Wl,--build-id=none" case "$architecture" in - arm ) - # testcc "$CC" "$CFLAGS -mcpu=cortex-a9" && - # CFLAGS="$CFLAGS -mcpu=cortex-a9" - testcc "$CC" "\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" && CFLAGS="\ -$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux \ --mno-thumb-interwork -march=armv7 -mno-thumb-interwork" + armv7 ) + ARMFLAGS="" + testcc "$CC" "$CFLAGS $ARMFLAGS"&&CFLAGS="$CFLAGS $ARMFLAGS" ;; esac } From gerrit at coreboot.org Fri Jan 4 00:48:49 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 00:48:49 +0100 Subject: [coreboot] Patch merged into coreboot/master: 10c90d3 update CFLAGS for armv7 References: Message-ID: the following patch was just integrated into master: commit 10c90d31264b5698320a1ac2666823532d110258 Author: David Hendricks Date: Thu Dec 27 13:30:55 2012 -0800 update CFLAGS for armv7 This updates $CFLAGS used for armv7. Most of them were just added to be consistent with what u-boot does. The important ones here are -march=armv7-a and -mthumb (to allow 16-bit Thumb instructions). I removed the hard float support because it got errors and coreboot should never use floats anyway. We're still having trouble with enums but I want to see how far it gets with this patch. Also, put the flags in a form that makes diffs easier to read. It's almost impossible otherwise. Finally, move some flags to the architecture Makefile, and rely on the fact that some are set for all architectures. Depends-On: I6f730d017391f9ec4401cdfd34931c869df10a9e Change-Id: Ia8a1ae22959933e06f7b996d1832cea40819f1ff Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/2075 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer Build-Tested: build bot (Jenkins) at Fri Jan 4 00:45:50 2013, giving +1 Reviewed-By: Stefan Reinauer at Fri Jan 4 00:48:12 2013, giving +2 See http://review.coreboot.org/2075 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 01:18:51 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Fri, 4 Jan 2013 01:18:51 +0100 Subject: [coreboot] Patch set updated for coreboot: 28ed5e7 make early serial console support more generic References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2086 -gerrit commit 28ed5e78f6d195ea63755a457b962620a2603467 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. uart.h now includes all .h files for all uarts. All 2 of them. This is actually a simplifying change. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/console/Kconfig | 7 +++++++ src/console/Makefile.inc | 2 +- src/console/console.c | 4 +++- src/cpu/Kconfig | 1 + src/cpu/samsung/Kconfig | 1 + src/cpu/samsung/exynos5250/uart.c | 6 +++--- src/cpu/samsung/exynos5250/uart.h | 1 + src/include/uart.h | 22 ++++++++++++++++------ src/include/uart8250.h | 1 - 9 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/console/Kconfig b/src/console/Kconfig index 117fdb8..b1f41de 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -5,6 +5,13 @@ config SERIAL_CONSOLE help Send coreboot debug output to a serial port +config EARLY_SERIAL_CONSOLE + bool + depends on SERIAL_CONSOLE + default n + help + Use serial console during early (pre-RAM) boot stages + config CONSOLE_SERIAL8250 bool "Serial port console output (I/O mapped, 8250-compatible)" depends on SERIAL_CONSOLE diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index a712486..3c4777f 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -10,7 +10,7 @@ smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c romstage-y += vtxprintf.c -romstage-$(CONFIG_CACHE_AS_RAM) += console.c +romstage-$(CONFIG_EARLY_SERIAL_CONSOLE) += console.c romstage-y += post.c romstage-y += die.c diff --git a/src/console/console.c b/src/console/console.c index d5f25a5..ad8f217 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -99,13 +99,15 @@ int console_tst_byte(void) #else // __PRE_RAM__ ^^^ NOT defined vvv defined +#include + void console_init(void) { #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); early_usbdebug_init(); #endif -#if CONFIG_CONSOLE_SERIAL8250 +#if CONFIG_HAVE_UART_IO_MAPPED || CONFIG_HAVE_UART_MEMORY_MAPPED uart_init(); #endif #if CONFIG_DRIVERS_OXFORD_OXPCIE && CONFIG_CONSOLE_SERIAL8250MEM diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 383ba79..ddc46cf 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -16,6 +16,7 @@ source src/cpu/x86/Kconfig config CACHE_AS_RAM bool + select EARLY_SERIAL_CONSOLE default !ROMCC config DCACHE_RAM_BASE diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 4a09ca3..abfc049 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 select CPU_SAMSUNG_EXYNOS + select EARLY_SERIAL_CONSOLE bool default n diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 3d43976..2d7bf38 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -23,6 +23,7 @@ //#include //#include +#include #include #include //#include @@ -34,7 +35,6 @@ #include #include -#include #define RX_FIFO_COUNT_MASK 0xff #define RX_FIFO_FULL_MASK (1 << 8) @@ -218,12 +218,12 @@ static const struct console_driver exynos5_uart_console __console = { //unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; //void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; /* FIXME: trivial wrappers */ -void uart_init() +void uart_init(void) { exynos5_init_dev(); } -unsigned char uart_rx_byte() +unsigned char uart_rx_byte(void) { return exynos5_uart_rx_byte(); } diff --git a/src/cpu/samsung/exynos5250/uart.h b/src/cpu/samsung/exynos5250/uart.h index 8190c67..033d605 100644 --- a/src/cpu/samsung/exynos5250/uart.h +++ b/src/cpu/samsung/exynos5250/uart.h @@ -68,4 +68,5 @@ static inline int s5p_uart_divslot(void) return 0; } +void uart_init(void); #endif diff --git a/src/include/uart.h b/src/include/uart.h index 931d6dc..6628314 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -15,19 +15,29 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * FIXME(dhendrix): This file contains generic prototypes for UART functions. - * The existing headers are too specific to the 8250, so we need a better - * abstraction for use with non-8250 UARTs. */ +/* madness. Uarts are a mess. If you include this file, it + * includes ALL uart implementations which may be needed. + * No need to include them separately, and include this file FIRST. + * At least one (but at most one) of the files needs to define + * uart_init(). + */ #ifndef UART_H #define UART_H +#if CONFIG_CONSOLE_SERIAL8250 +#include +#endif + +#if CONFIG_CPU_SAMSUNG_EXYNOS5 +#include +#endif + +#ifndef __ROMCC__ unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); - -void uart_init(void); +#endif #endif /* UART_H */ diff --git a/src/include/uart8250.h b/src/include/uart8250.h index b00ff48..9af43f2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -120,7 +120,6 @@ unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); void uart8250_tx_byte(unsigned base_port, unsigned char data); void uart8250_tx_flush(unsigned base_port); - /* Yes it is silly to have three different uart init functions. But we used to * have three different sets of uart code, so it's an improvement. */ From gerrit at coreboot.org Fri Jan 4 01:36:29 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 01:36:29 +0100 Subject: [coreboot] Patch merged into coreboot/master: 6a503b6 make early serial console support more generic References: Message-ID: the following patch was just integrated into master: commit 6a503b6a0f08bf4236c4c37d75c67182a7af4b02 Author: David Hendricks Date: Mon Dec 31 17:28:43 2012 -0800 make early serial console support more generic This patch makes pre-RAM serial init more generic, particularly for platforms which do not necessarily need cache-as-RAM in order to use the serial console and do not have a standard 8250 serial port. This adds a Kconfig variable to set romstage-* for very early serial console init. The current method assumes that cache-as-RAM should enable this, so to maintain compatibility selecting CACHE_AS_RAM will also select EARLY_SERIAL_CONSOLE. The UART code structure needs some rework, but the use of ROMCC, romstage, and then ramstage makes things complex. uart.h now includes all .h files for all uarts. All 2 of them. This is actually a simplifying change. Change-Id: I089e7af633c227baf3c06c685f005e9d0e4b38ce Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/2086 Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Fri Jan 4 01:30:21 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 01:36:27 2013, giving +2 See http://review.coreboot.org/2086 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 01:36:52 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 01:36:52 +0100 Subject: [coreboot] Patch merged into coreboot/master: 801467f enable early serial console on exynos5250 References: Message-ID: the following patch was just integrated into master: commit 801467f30ad08a69fa4a1ce84b5aeddabecd1185 Author: David Hendricks Date: Mon Dec 31 17:55:29 2012 -0800 enable early serial console on exynos5250 Change-Id: Ib16308c72b86860e80caec96202c42991a7b1d1a Signed-off-by: David Hendricks Reviewed-on: http://review.coreboot.org/2085 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Thu Jan 3 20:08:02 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 01:36:48 2013, giving +2 See http://review.coreboot.org/2085 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 01:37:06 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Fri, 4 Jan 2013 01:37:06 +0100 Subject: [coreboot] Patch set updated for coreboot: 1310fe8 cleanup some exynos5250 uart code References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2084 -gerrit commit 1310fe8fb95be9c33952e4873bc8cd7eb93de9d8 Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. A bit of cleanup based on earlier patches. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich --- src/cpu/samsung/exynos5250/uart.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/cpu/samsung/exynos5250/uart.c index 2d7bf38..b219f48 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/cpu/samsung/exynos5250/uart.c @@ -21,15 +21,9 @@ * */ -//#include -//#include #include #include #include -//#include -//#include -//#include -//#include #include /* for __console definition */ @@ -180,8 +174,6 @@ static unsigned char exynos5_uart_rx_byte(void) /* * Output a single byte to the serial port. */ -/* FIXME: ordering of arguments for coreboot v. u-boot for tx_byte */ -//static void exynos5_tx_byte(const char c, const int dev_index) static void exynos5_uart_tx_byte(unsigned char data) { // struct s5p_uart *const uart = s5p_get_base_uart(dev_index); @@ -198,14 +190,6 @@ static void exynos5_uart_tx_byte(unsigned char data) #ifndef __PRE_RAM__ static const struct console_driver exynos5_uart_console __console = { -//static const struct console_driver exynos5_uart_console __console = { -#if 0 - void (*init)(void); - void (*tx_byte)(unsigned char byte); - void (*tx_flush)(void); - unsigned char (*rx_byte)(void); - int (*tst_byte)(void); -#endif .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, // .tx_flush = exynos5_uart_tx_flush, @@ -213,11 +197,6 @@ static const struct console_driver exynos5_uart_console __console = { // .tst_byte = exynos5_uart_tst_byte, }; #else -/* for romstage_console... */ -//void (*uart_init)(void) = exynos5_init_dev; -//unsigned char (*uart_rx_byte)(unsigned base_port) = exynos5_uart_rx_byte; -//void (*uart_tx_byte)(unsigned base_port, unsigned char data) = exynos5_uart_tx_byte; -/* FIXME: trivial wrappers */ void uart_init(void) { exynos5_init_dev(); From gerrit at coreboot.org Fri Jan 4 01:45:27 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 01:45:27 +0100 Subject: [coreboot] Patch merged into coreboot/master: 858b650 cleanup some exynos5250 uart code References: Message-ID: the following patch was just integrated into master: commit 858b65028e02d4e2460a9f6033aec570006b9d0b Author: David Hendricks Date: Mon Dec 31 17:56:22 2012 -0800 cleanup some exynos5250 uart code This just cleans out some unused headers and tidies up the early serial code. TODO: Clean-up or replace FDT code, make "base_port" easier to configure. A bit of cleanup based on earlier patches. Change-Id: Ie77ee6d4935346e0053c09252055662f1a45d5f5 Signed-off-by: David Hendricks Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/2084 Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Fri Jan 4 01:43:41 2013, giving +1 Reviewed-By: David Hendricks at Fri Jan 4 01:38:27 2013, giving +2 Reviewed-By: Ronald G. Minnich at Fri Jan 4 01:45:26 2013, giving +2 See http://review.coreboot.org/2084 for details. -gerrit From david.c.hubbard+coreboot at gmail.com Fri Jan 4 03:54:39 2013 From: david.c.hubbard+coreboot at gmail.com (David Hubbard) Date: Thu, 3 Jan 2013 19:54:39 -0700 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: On Thu, Jan 3, 2013 at 4:23 PM, gary sheppard wrote: > I very much wish people would listen to what Ron just said! > > As for why they are lining up behind it? Personally I think they are > afraid to be seen as "reactionary" and against "progress". After all > "everyone" knows secureboot will make life in computing land *Perfect*! The > way it has been dressed up and loudly presented to World_+_Dog makes it > seem as though anyone against it is against "progress"! > > Numerous security experts have already said it is anything but secure, and > it will never be secure. They have only said this quietly, and that "voice" > has been minimalized, while "PROGRESS" is shouted to the heavens. Hey, look > at android and how phone makers "lock" it down. Does it stay locked? No! > Come on people, put your heads out of... ;) > > Gary > When the FSF has been right and "everyone in the open source community" opposed them, they didn't back down. I put "everyone..." in quotes because it hasn't always been the same community, but I do feel that the term open source isn't used by the FSF for a good reason. I'm not trying to attack people for talking about the open source community -- rather, I believe the FSF was successful for example in establishing the GPL as a popular license specifically because they had the right approach. I think they did what Mahatma Gandhi did, which was to carefully evaluate what response would *work* and then keep executing on that, basically flawlessly, until it did work. A counterexample would have been the Hurd kernel, because it apparently wasn't executed right (again, not trying to pick on something) -- but if the idea is sound, it could still be pulled off. The FSF has taken lots of dings over the years for standing up for what they believed, but they have still succeeded. If Secure Boot is a bad idea (I believe it is) -- no need to attack corporate-sponsored efforts to line up behind it. I personally use Gentoo Linux which means my kernels are compiled right on my own box. Secure Boot will never work for that (specifically, getting each kernel signed for each user would never scale). Sure, I could use a shim but for me that's equivalent to accepting defeat. I suppose we could thank the corporate-sponsored bootloaders that will make an easy path to boot and install linux during this period of uncertainty. However, Ron, let me buy you a drink sometime: we need a better solution. Coreboot could do that. "Never give in. Never give in. Never, never, never, never?in nothing, great or small, large or petty?never give in, except to convictions of honour and good sense. Never yield to force. Never yield to the apparently overwhelming might of the enemy." David -------------- next part -------------- An HTML attachment was scrubbed... URL: From gerrit at coreboot.org Fri Jan 4 05:36:27 2013 From: gerrit at coreboot.org (Hung-Te Lin (hungte@chromium.org)) Date: Fri, 4 Jan 2013 05:36:27 +0100 Subject: [coreboot] New patch to review for coreboot: 1c862b0 Change "VERSION*" to more determined name "CBFS_HEADER_VERSION*". References: Message-ID: Hung-Te Lin (hungte at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2098 -gerrit commit 1c862b03e4f8602090679001ee18a684f16fec37 Author: Hung-Te Lin Date: Fri Jan 4 12:33:03 2013 +0800 Change "VERSION*" to more determined name "CBFS_HEADER_VERSION*". The 'VERSION' in CBFS header file is confusing and may conflict when being used in libpayload. Change-Id: I24cce0cd73540e38d96f222df0a65414b16f6260 Signed-off-by: Hung-Te Lin --- payloads/libpayload/include/cbfs_core.h | 6 +++--- src/include/cbfs_core.h | 6 +++--- util/cbfstool/cbfs.h | 6 +++--- util/cbfstool/common.c | 6 +++--- util/nvramtool/cbfs.h | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h index 9a21a78..a3c54b1 100644 --- a/payloads/libpayload/include/cbfs_core.h +++ b/payloads/libpayload/include/cbfs_core.h @@ -88,9 +88,9 @@ /* FIXME: This could also be 0xFFFF0000 with HIVECS enabled */ #define CBFS_HEADPTR_ADDR 0x0000000C #endif -#define VERSION1 0x31313131 -#define VERSION2 0x31313132 -#define VERSION VERSION2 +#define CBFS_HEADER_VERSION1 0x31313131 +#define CBFS_HEADER_VERSION2 0x31313132 +#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 struct cbfs_header { uint32_t magic; diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h index 9a21a78..a3c54b1 100644 --- a/src/include/cbfs_core.h +++ b/src/include/cbfs_core.h @@ -88,9 +88,9 @@ /* FIXME: This could also be 0xFFFF0000 with HIVECS enabled */ #define CBFS_HEADPTR_ADDR 0x0000000C #endif -#define VERSION1 0x31313131 -#define VERSION2 0x31313132 -#define VERSION VERSION2 +#define CBFS_HEADER_VERSION1 0x31313131 +#define CBFS_HEADER_VERSION2 0x31313132 +#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 struct cbfs_header { uint32_t magic; diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h index 5251d65..617eeee 100644 --- a/util/cbfstool/cbfs.h +++ b/util/cbfstool/cbfs.h @@ -23,9 +23,9 @@ #define CBFS_HEADER_MAGIC 0x4F524243 #define CBFS_HEADPTR_ADDR_X86 0xFFFFFFFC -#define VERSION1 0x31313131 -#define VERSION2 0x31313132 -#define VERSION VERSION2 +#define CBFS_HEADER_VERSION1 0x31313131 +#define CBFS_HEADER_VERSION2 0x31313132 +#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 struct cbfs_header { uint32_t magic; diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index befdc3f..3b63e54 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -143,7 +143,7 @@ void recalculate_rom_geometry(void *romarea) } /* Update old headers */ - if (master_header->version == VERSION1 && + if (master_header->version == CBFS_HEADER_VERSION1 && ntohl(master_header->architecture) == CBFS_ARCHITECTURE_UNKNOWN) { dprintf("Updating CBFS master header to version 2\n"); master_header->architecture = htonl(CBFS_ARCHITECTURE_X86); @@ -583,7 +583,7 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize, arm_vec[0] = htonl(0x0e0000ea); // branch to . + 64 bytes master_header->magic = ntohl(CBFS_HEADER_MAGIC); - master_header->version = ntohl(VERSION); + master_header->version = ntohl(CBFS_HEADER_VERSION); master_header->romsize = htonl(romsize); master_header->bootblocksize = htonl(bootblocksize); master_header->align = htonl(align); @@ -612,7 +612,7 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize, bootblocksize - sizeof(struct cbfs_header)); master_header->magic = ntohl(CBFS_HEADER_MAGIC); - master_header->version = ntohl(VERSION); + master_header->version = ntohl(CBFS_HEADER_VERSION); master_header->romsize = htonl(romsize); master_header->bootblocksize = htonl(bootblocksize); master_header->align = htonl(align); diff --git a/util/nvramtool/cbfs.h b/util/nvramtool/cbfs.h index 5f9db8d..bf5ca95 100644 --- a/util/nvramtool/cbfs.h +++ b/util/nvramtool/cbfs.h @@ -89,7 +89,7 @@ typedef uint8_t u8; #define CBFS_HEADER_MAGIC 0x4F524243 #define CBFS_HEADPTR_ADDR 0xFFFFFFFc -#define VERSION1 0x31313131 +#define CBFS_HEADER_VERSION1 0x31313131 struct cbfs_header { u32 magic; From gerrit at coreboot.org Fri Jan 4 06:08:14 2013 From: gerrit at coreboot.org (Siyuan Wang (wangsiyuanbuaa@gmail.com)) Date: Fri, 4 Jan 2013 06:08:14 +0100 Subject: [coreboot] New patch to review for coreboot: ebf80ba Tyan s8226: change lapic of lapic_cluster 0 to 0x10 References: Message-ID: Siyuan Wang (wangsiyuanbuaa at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2099 -gerrit commit ebf80ba8cf29cf28ce37e06d82458cab61095af6 Author: Siyuan Wang Date: Fri Jan 4 13:07:49 2013 +0800 Tyan s8226: change lapic of lapic_cluster 0 to 0x10 There are two CPUs on s8226 and each CPU has 8 cores. CPU 0 takes lapic from 0x10 to 0x17 and CPU 1 takes from 0x20 to 0x27. So the first core's lapic is 0x10 rather than 0x20. Change-Id: I925114d44f2f4974eb62c3832d8c9139a2a06c96 Signed-off-by: Siyuan Wang Signed-off-by: Siyuan Wang --- src/mainboard/tyan/s8226/devicetree.cb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mainboard/tyan/s8226/devicetree.cb b/src/mainboard/tyan/s8226/devicetree.cb index 4459019..a057f02 100644 --- a/src/mainboard/tyan/s8226/devicetree.cb +++ b/src/mainboard/tyan/s8226/devicetree.cb @@ -19,8 +19,7 @@ chip northbridge/amd/agesa/family15/root_complex device lapic_cluster 0 on chip cpu/amd/agesa/family15 - device lapic 0x20 on end #f15 - #device lapic 0x10 on end #f10 + device lapic 0x10 on end end end device pci_domain 0 on From gerrit at coreboot.org Fri Jan 4 06:27:33 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 06:27:33 +0100 Subject: [coreboot] Patch merged into coreboot/master: 086842a Change "VERSION*" to more determined name "CBFS_HEADER_VERSION*". References: Message-ID: the following patch was just integrated into master: commit 086842a13e50d2c870ddf749c036f8c321d2915f Author: Hung-Te Lin Date: Fri Jan 4 12:33:03 2013 +0800 Change "VERSION*" to more determined name "CBFS_HEADER_VERSION*". The 'VERSION' in CBFS header file is confusing and may conflict when being used in libpayload. Change-Id: I24cce0cd73540e38d96f222df0a65414b16f6260 Signed-off-by: Hung-Te Lin Reviewed-on: http://review.coreboot.org/2098 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks Build-Tested: build bot (Jenkins) at Fri Jan 4 05:43:05 2013, giving +1 Reviewed-By: David Hendricks at Fri Jan 4 06:27:32 2013, giving +2 See http://review.coreboot.org/2098 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 06:37:20 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 06:37:20 +0100 Subject: [coreboot] Patch merged into coreboot/master: 3d4762d Tyan s8226: change lapic of lapic_cluster 0 to 0x10 References: Message-ID: the following patch was just integrated into master: commit 3d4762d450f63c32038b4c9c422dc99c98fdee9a Author: Siyuan Wang Date: Fri Jan 4 13:07:49 2013 +0800 Tyan s8226: change lapic of lapic_cluster 0 to 0x10 There are two CPUs on s8226 and each CPU has 8 cores. CPU 0 takes lapic from 0x10 to 0x17 and CPU 1 takes from 0x20 to 0x27. So the first core's lapic is 0x10 rather than 0x20. Change-Id: I925114d44f2f4974eb62c3832d8c9139a2a06c96 Signed-off-by: Siyuan Wang Signed-off-by: Siyuan Wang Reviewed-on: http://review.coreboot.org/2099 Reviewed-by: Zheng Bao Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Fri Jan 4 06:15:14 2013, giving +1 Reviewed-By: Zheng Bao at Fri Jan 4 06:10:47 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 06:37:18 2013, giving +2 See http://review.coreboot.org/2099 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 06:38:02 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 06:38:02 +0100 Subject: [coreboot] Patch merged into coreboot/master: 05cbce6 cbmem utility: Use mmap instead of fseek/fread References: Message-ID: the following patch was just integrated into master: commit 05cbce672e4a41bc55fc09b65aacd0872a756a5b Author: Stefan Reinauer Date: Thu Jan 3 14:30:33 2013 -0800 cbmem utility: Use mmap instead of fseek/fread The kernel on Ubuntu 12.04LTS does not allow to use fseek/fread to read the coreboot table at the end of memory but will instead abort cbmem with a "Bad Address" error. Whether that is a security feature (some variation of CONFIG_STRICT_DEVMEM) or a kernel bug is not yet clear, however using mmap works nicely. Change-Id: I796b4cd2096fcdcc65c1361ba990cd467f13877e Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2097 Reviewed-by: Ronald G. Minnich Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Thu Jan 3 23:55:16 2013, giving +1 Reviewed-By: Ronald G. Minnich at Thu Jan 3 23:53:35 2013, giving +2 See http://review.coreboot.org/2097 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 06:38:25 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 06:38:25 +0100 Subject: [coreboot] Patch merged into coreboot/master: 9027845 rd890: clear IO-APIC before setup References: Message-ID: the following patch was just integrated into master: commit 9027845d65e5e05a45894eb176070fd99e2e073c Author: Aladyshev Konstantin Date: Tue Dec 18 22:44:01 2012 +0400 rd890: clear IO-APIC before setup Add function "clear_ioapic" before "setup_ioapic" for RD890 northbridge like it is done for SB700 and SB800 chipsets ("amd/cimx/sb{7,8}00"). No functionality change is noticed. Change-Id: I1fd87692d8bf35c166141c9b7a6a1e748c19a636 Signed-off-by: Aladyshev Konstantin Reviewed-on: http://review.coreboot.org/2045 Tested-by: build bot (Jenkins) Reviewed-by: Zheng Bao Reviewed-by: Stefan Reinauer Build-Tested: build bot (Jenkins) at Wed Dec 19 18:47:57 2012, giving +1 Reviewed-By: Stefan Reinauer at Thu Jan 3 23:45:08 2013, giving +2 Reviewed-By: Zheng Bao at Wed Jan 2 11:13:36 2013, giving +1 See http://review.coreboot.org/2045 for details. -gerrit From rhyotte at gmail.com Fri Jan 4 00:23:48 2013 From: rhyotte at gmail.com (gary sheppard) Date: Thu, 3 Jan 2013 15:23:48 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: I very much wish people would listen to what Ron just said! As for why they are lining up behind it? Personally I think they are afraid to be seen as "reactionary" and against "progress". After all "everyone" knows secureboot will make life in computing land *Perfect*! The way it has been dressed up and loudly presented to World_+_Dog makes it seem as though anyone against it is against "progress"! Numerous security experts have already said it is anything but secure, and it will never be secure. They have only said this quietly, and that "voice" has been minimalized, while "PROGRESS" is shouted to the heavens. Hey, look at android and how phone makers "lock" it down. Does it stay locked? No! Come on people, put your heads out of... ;) Gary On Thu, Jan 3, 2013 at 10:40 AM, ron minnich wrote: > OK, after further thought, here's my take. > > Two companies have defined a secure boot standard in such a way that > they can closely control what boots on future systems using the one > company's chips. This is a sea change from the original IBM PC design, > which encouraged people to boot anything, and included the > (copyrighted) BIOS listing on paper to further that end. > > The current state is that the software company is becoming the > gatekeeper for what OS will run on systems built using the hardware > company's chips. Their end goal is that the software company becomes > the gatekeeper for what runs on almost *anything* -- not just x86. > Don't believe me? Read about ARM systems and Windows 8. > > Vendors are now building systems based on this standard. People are > seeing that the situation is not quite as blissful as the two > companies have painted it -- that certain software will in fact be > locked out for a number of reasons, that there can be unexplained > delays in getting code signed, and that buggy EFI implementations may > lock people out in unforeseen ways. > > The open source community's response has been to act in a way that > strengthens this model. They're doing all they can to find a way to > work inside these limits. Instead of pushing hard to use only hardware > that's really open, and doing what they can to relegate this (shown to > be insecure) "secure" boot to the dustbin of history, they're pushing > as hard as they can to make it succeed. > > I find this quite perverse. There's lots of good hardware out there > that is not built around this lockin, and yet the open source > community is focusing lots of effort on making the lockin viable. > > The open source community has pushed back on defective standards like > this before and won. Why they're rolling over now is a puzzling, > especially given the existence of alternatives. Put another way, I > think the secure boot standard needs the open source community more > than the open source community needs the secure boot standard, but the > open source community is not exploiting that fact. I guess part of it > is that so much of the open source community is contained in big > companies, but it's stil disappointing. > > ron > > -- > coreboot mailing list: coreboot at coreboot.org > http://www.coreboot.org/mailman/listinfo/coreboot > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gerrit at coreboot.org Fri Jan 4 18:58:32 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 18:58:32 +0100 Subject: [coreboot] Patch set updated for coreboot: c6ba074 armv7: invoke intermediate build rules References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit c6ba0743b2bdf7c331d43161fd8178d3274dca47 Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 9e57244..301866c 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Fri Jan 4 19:08:35 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 19:08:35 +0100 Subject: [coreboot] New patch to review for coreboot: 4bc29b5 Make PCIe config options depend on PCIe support References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2100 -gerrit commit 4bc29b5e870a382723d23b5f52f1cfe77575f16f Author: Stefan Reinauer Date: Fri Jan 4 10:07:28 2013 -0800 Make PCIe config options depend on PCIe support Change-Id: I42452a044dc75e35876fcea1736481e538eed663 Signed-off-by: Stefan Reinauer --- src/device/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device/Kconfig b/src/device/Kconfig index 849cc15..82583a4 100644 --- a/src/device/Kconfig +++ b/src/device/Kconfig @@ -212,6 +212,7 @@ config CARDBUS_PLUGIN_SUPPORT config PCIEXP_COMMON_CLOCK prompt "Enable PCIe Common Clock" bool + depends on PCIEXP_PLUGIN_SUPPORT default n help Detect and enable Common Clock on PCIe links. @@ -219,6 +220,7 @@ config PCIEXP_COMMON_CLOCK config PCIEXP_ASPM prompt "Enable PCIe ASPM" bool + depends on PCIEXP_PLUGIN_SUPPORT default n help Detect and enable ASPM on PCIe links. From gerrit at coreboot.org Fri Jan 4 19:14:08 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 19:14:08 +0100 Subject: [coreboot] New patch to review for coreboot: 555bf7d Clean up ARMv7 architecture Kconfig References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2101 -gerrit commit 555bf7db826824c0166d613753ea77e794964968 Author: Stefan Reinauer Date: Fri Jan 4 10:11:59 2013 -0800 Clean up ARMv7 architecture Kconfig There was a misuse of bool that would cause the dcache policy to not be set up correctly, but instead present options "y" and "n" in the Kconfig menu. Also, TINY_BOOTBLOCK was removed a while ago, everything is TINY_BOOTBLOCK now. Hence remove the option. Change-Id: I5c28ac828955c69614c7bdaf106f79db51e68723 Signed-off-by: Stefan Reinauer --- src/arch/armv7/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arch/armv7/Kconfig b/src/arch/armv7/Kconfig index f92911d..65de2d5 100644 --- a/src/arch/armv7/Kconfig +++ b/src/arch/armv7/Kconfig @@ -34,7 +34,6 @@ config BOOTBLOCK_SOURCE config UPDATE_IMAGE bool "Update existing coreboot.rom image" default n - depends on TINY_BOOTBLOCK help If this option is enabled, no new coreboot.rom file is created. Instead it is expected that there already @@ -47,9 +46,11 @@ config BOOTBLOCK_SOC_INIT # FIXME: Should cache policy be set on a per-CPU basis? # FIXME(dhendrix): Stefan sayz to make a smart decision and not prompt the user. config ARM_DCACHE_POLICY_WRITEBACK - bool y + bool + default y config ARM_DCACHE_POLICY_WRITETHROUGH - bool n + bool + default n endmenu From gerrit at coreboot.org Fri Jan 4 19:35:15 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 19:35:15 +0100 Subject: [coreboot] Patch merged into coreboot/master: c4077d4 Make PCIe config options depend on PCIe support References: Message-ID: the following patch was just integrated into master: commit c4077d44297c95100cc9eb19df1ab3b16261942f Author: Stefan Reinauer Date: Fri Jan 4 10:07:28 2013 -0800 Make PCIe config options depend on PCIe support Change-Id: I42452a044dc75e35876fcea1736481e538eed663 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2100 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Fri Jan 4 19:19:34 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 19:35:14 2013, giving +2 See http://review.coreboot.org/2100 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 19:35:25 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 19:35:25 +0100 Subject: [coreboot] Patch merged into coreboot/master: 31c3613 Clean up ARMv7 architecture Kconfig References: Message-ID: the following patch was just integrated into master: commit 31c36137f9519380df0c92ce1a5d2949eb083b91 Author: Stefan Reinauer Date: Fri Jan 4 10:11:59 2013 -0800 Clean up ARMv7 architecture Kconfig There was a misuse of bool that would cause the dcache policy to not be set up correctly, but instead present options "y" and "n" in the Kconfig menu. Also, TINY_BOOTBLOCK was removed a while ago, everything is TINY_BOOTBLOCK now. Hence remove the option. Change-Id: I5c28ac828955c69614c7bdaf106f79db51e68723 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2101 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Fri Jan 4 19:29:46 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 19:34:50 2013, giving +2 See http://review.coreboot.org/2101 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 21:13:02 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 21:13:02 +0100 Subject: [coreboot] Patch set updated for coreboot: d63e5d5 armv7: invoke intermediate build rules References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit d63e5d5e12f8a8223cb4908afaaa6bf808f93079 Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 9e57244..301866c 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Fri Jan 4 21:13:02 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 21:13:02 +0100 Subject: [coreboot] New patch to review for coreboot: 3cc3cc1 ARMv7: drop libgcc copy References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2102 -gerrit commit 3cc3cc12e6d26ed8562ec63c253dd8ca624cea0f Author: Stefan Reinauer Date: Fri Jan 4 12:10:28 2013 -0800 ARMv7: drop libgcc copy We accidently checked in some files from libgcc as well as a Makefile from u-boot and a duplicate implementation of div0. Drop all those files to reduce the confusion. Change-Id: I8ff6eabbced6f663813f8cc55f19c81839d03477 Signed-off-by: Stefan Reinauer --- src/arch/armv7/lib/Makefile.inc | 1 - src/arch/armv7/lib/Makefile.uboot | 95 ----------------------- src/arch/armv7/lib/_divsi3.S | 142 ---------------------------------- src/arch/armv7/lib/_udivsi3.S | 93 ---------------------- src/arch/armv7/lib/_uldivmod.S | 157 -------------------------------------- src/arch/armv7/lib/div.c | 5 -- 6 files changed, 493 deletions(-) diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc index bdf6a64..d911341 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -11,7 +11,6 @@ romstage-y += syslib.c ramstage-y += c_start.S -#ramstage-y += div.c ramstage-y += div0.c ramstage-y += div64.S ramstage-y += hang_spl.c diff --git a/src/arch/armv7/lib/Makefile.uboot b/src/arch/armv7/lib/Makefile.uboot deleted file mode 100644 index d33d08b..0000000 --- a/src/arch/armv7/lib/Makefile.uboot +++ /dev/null @@ -1,95 +0,0 @@ -# -# (C) Copyright 2002-2006 -# Wolfgang Denk, DENX Software Engineering, wd at denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB = $(obj)lib$(ARCH).o -LIBGCC = $(obj)libgcc.o - -ifndef CONFIG_SPL_BUILD -GLSOBJS += _ashldi3.o -GLSOBJS += _ashrdi3.o -GLSOBJS += _divsi3.o -GLSOBJS += _lshrdi3.o -GLSOBJS += _modsi3.o -GLSOBJS += _udivsi3.o -GLSOBJS += _umodsi3.o -ifdef CONFIG_CHROMEOS -GLSOBJS += _uldivmod.o -endif - -GLCOBJS += div0.o - -ifeq ($(CONFIG_SYS_GENERIC_BOARD),) -COBJS-y += board.o -endif -COBJS-y += bootm.o -COBJS-y += cache.o -COBJS-y += cache-cp15.o -COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o -SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o -SOBJS-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o -else # CONFIG_SPL_BUILD -ifeq ($(CONFIG_SYS_GENERIC_BOARD),) -COBJS-y += hang_spl.o -endif -endif # CONFIG_SPL_BUILD - -COBJS-y += interrupts.o -COBJS-y += reset.o - -SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \ - $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) -LGOBJS := $(addprefix $(obj),$(GLSOBJS)) \ - $(addprefix $(obj),$(GLCOBJS)) - -# Always build libarm.o -TARGETS := $(LIB) - -# Build private libgcc only when asked for -ifdef USE_PRIVATE_LIBGCC -TARGETS += $(LIBGCC) -endif - -# For EABI conformant tool chains, provide eabi_compat() -ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) -TARGETS += $(obj)eabi_compat.o -endif - -all: $(TARGETS) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -$(LIBGCC): $(obj).depend $(LGOBJS) - $(call cmd_link_o_target, $(LGOBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/src/arch/armv7/lib/_divsi3.S b/src/arch/armv7/lib/_divsi3.S deleted file mode 100644 index cfbadb2..0000000 --- a/src/arch/armv7/lib/_divsi3.S +++ /dev/null @@ -1,142 +0,0 @@ - -.macro ARM_DIV_BODY dividend, divisor, result, curbit - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \curbit, \divisor - clz \result, \dividend - sub \result, \curbit, \result - mov \curbit, #1 - mov \divisor, \divisor, lsl \result - mov \curbit, \curbit, lsl \result - mov \result, #0 - -#else - - @ Initially shift the divisor left 3 bits if possible, - @ set curbit accordingly. This allows for curbit to be located - @ at the left end of each 4 bit nibbles in the division loop - @ to save one loop in most cases. - tst \divisor, #0xe0000000 - moveq \divisor, \divisor, lsl #3 - moveq \curbit, #8 - movne \curbit, #1 - - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. -1: cmp \divisor, #0x10000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #4 - movlo \curbit, \curbit, lsl #4 - blo 1b - - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. -1: cmp \divisor, #0x80000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #1 - movlo \curbit, \curbit, lsl #1 - blo 1b - - mov \result, #0 - -#endif - - @ Division loop -1: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - orrhs \result, \result, \curbit - cmp \dividend, \divisor, lsr #1 - subhs \dividend, \dividend, \divisor, lsr #1 - orrhs \result, \result, \curbit, lsr #1 - cmp \dividend, \divisor, lsr #2 - subhs \dividend, \dividend, \divisor, lsr #2 - orrhs \result, \result, \curbit, lsr #2 - cmp \dividend, \divisor, lsr #3 - subhs \dividend, \dividend, \divisor, lsr #3 - orrhs \result, \result, \curbit, lsr #3 - cmp \dividend, #0 @ Early termination? - movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? - movne \divisor, \divisor, lsr #4 - bne 1b - -.endm - -.macro ARM_DIV2_ORDER divisor, order - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \order, \divisor - rsb \order, \order, #31 - -#else - - cmp \divisor, #(1 << 16) - movhs \divisor, \divisor, lsr #16 - movhs \order, #16 - movlo \order, #0 - - cmp \divisor, #(1 << 8) - movhs \divisor, \divisor, lsr #8 - addhs \order, \order, #8 - - cmp \divisor, #(1 << 4) - movhs \divisor, \divisor, lsr #4 - addhs \order, \order, #4 - - cmp \divisor, #(1 << 2) - addhi \order, \order, #3 - addls \order, \order, \divisor, lsr #1 - -#endif - -.endm - - .align 5 -.globl __divsi3 -.globl __aeabi_idiv -__divsi3: -__aeabi_idiv: - cmp r1, #0 - eor ip, r0, r1 @ save the sign of the result. - beq Ldiv0 - rsbmi r1, r1, #0 @ loops below use unsigned. - subs r2, r1, #1 @ division by 1 or -1 ? - beq 10f - movs r3, r0 - rsbmi r3, r0, #0 @ positive dividend value - cmp r3, r1 - bls 11f - tst r1, r2 @ divisor is power of 2 ? - beq 12f - - ARM_DIV_BODY r3, r1, r0, r2 - - cmp ip, #0 - rsbmi r0, r0, #0 - mov pc, lr - -10: teq ip, r0 @ same sign ? - rsbmi r0, r0, #0 - mov pc, lr - -11: movlo r0, #0 - moveq r0, ip, asr #31 - orreq r0, r0, #1 - mov pc, lr - -12: ARM_DIV2_ORDER r1, r2 - - cmp ip, #0 - mov r0, r3, lsr r2 - rsbmi r0, r0, #0 - mov pc, lr - -Ldiv0: - - str lr, [sp, #-4]! - bl __div0 - mov r0, #0 @ About as wrong as it could be. - ldr pc, [sp], #4 diff --git a/src/arch/armv7/lib/_udivsi3.S b/src/arch/armv7/lib/_udivsi3.S deleted file mode 100644 index 1309802..0000000 --- a/src/arch/armv7/lib/_udivsi3.S +++ /dev/null @@ -1,93 +0,0 @@ -/* # 1 "libgcc1.S" */ -@ libgcc1 routines for ARM cpu. -@ Division routines, written by Richard Earnshaw, (rearnsha at armltd.co.uk) -dividend .req r0 -divisor .req r1 -result .req r2 -curbit .req r3 -/* ip .req r12 */ -/* sp .req r13 */ -/* lr .req r14 */ -/* pc .req r15 */ - .text - .globl __udivsi3 - .type __udivsi3 ,function - .globl __aeabi_uidiv - .type __aeabi_uidiv ,function - .align 0 - __udivsi3: - __aeabi_uidiv: - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - mov result, #0 - cmp dividend, divisor - bcc Lgot_result -Loop1: - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. - cmp divisor, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 -Lbignum: - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. - cmp divisor, #0x80000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum -Loop3: - @ Test for possible subtractions, and note which bits - @ are done in the result. On the final pass, this may subtract - @ too much from the dividend, but the result will be ok, since the - @ "bit" will have been shifted out at the bottom. - cmp dividend, divisor - subcs dividend, dividend, divisor - orrcs result, result, curbit - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs result, result, curbit, lsr #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs result, result, curbit, lsr #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs result, result, curbit, lsr #3 - cmp dividend, #0 @ Early termination? - movnes curbit, curbit, lsr #4 @ No, any more bits to do? - movne divisor, divisor, lsr #4 - bne Loop3 -Lgot_result: - mov r0, result - mov pc, lr -Ldiv0: - str lr, [sp, #-4]! - bl __div0 (PLT) - mov r0, #0 @ about as wrong as it could be - ldmia sp!, {pc} - .size __udivsi3 , . - __udivsi3 - -.globl __aeabi_uidivmod -__aeabi_uidivmod: - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_uidiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -.globl __aeabi_idivmod -__aeabi_idivmod: - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_idiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr diff --git a/src/arch/armv7/lib/_uldivmod.S b/src/arch/armv7/lib/_uldivmod.S deleted file mode 100644 index 65e4fa8..0000000 --- a/src/arch/armv7/lib/_uldivmod.S +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - */ - -/* - * A, Q = r0 + (r1 << 32) - * B, R = r2 + (r3 << 32) - * A / B = Q ... R - */ - - .text - .global __aeabi_uldivmod - .type __aeabi_uldivmod, function - .align 0 - -A_0 .req r0 -A_1 .req r1 -B_0 .req r2 -B_1 .req r3 -C_0 .req r4 -C_1 .req r5 -D_0 .req r6 -D_1 .req r7 - -Q_0 .req r0 -Q_1 .req r1 -R_0 .req r2 -R_1 .req r3 - -__aeabi_uldivmod: - stmfd sp!, {r4, r5, r6, r7, lr} - @ Test if B == 0 - orrs ip, B_0, B_1 @ Z set -> B == 0 - beq L_div_by_0 - @ Test if B is power of 2: (B & (B - 1)) == 0 - subs C_0, B_0, #1 - sbc C_1, B_1, #0 - tst C_0, B_0 - tsteq B_1, C_1 - beq L_pow2 - @ Test if A_1 == B_1 == 0 - orrs ip, A_1, B_1 - beq L_div_32_32 - -L_div_64_64: - mov C_0, #1 - mov C_1, #0 - @ D_0 = clz A - teq A_1, #0 - clz D_0, A_1 - clzeq ip, A_0 - addeq D_0, D_0, ip - @ D_1 = clz B - teq B_1, #0 - clz D_1, B_1 - clzeq ip, B_0 - addeq D_1, D_1, ip - @ if clz B - clz A > 0 - subs D_0, D_1, D_0 - bls L_done_shift - @ B <<= (clz B - clz A) - subs D_1, D_0, #32 - rsb ip, D_0, #32 - movmi B_1, B_1, lsl D_0 - orrmi B_1, B_1, B_0, lsr ip - movpl B_1, B_0, lsl D_1 - mov B_0, B_0, lsl D_0 - @ C = 1 << (clz B - clz A) - movmi C_1, C_1, lsl D_0 - orrmi C_1, C_1, C_0, lsr ip - movpl C_1, C_0, lsl D_1 - mov C_0, C_0, lsl D_0 -L_done_shift: - mov D_0, #0 - mov D_1, #0 - @ C: current bit; D: result -L_subtract: - @ if A >= B - cmp A_1, B_1 - cmpeq A_0, B_0 - bcc L_update - @ A -= B - subs A_0, A_0, B_0 - sbc A_1, A_1, B_1 - @ D |= C - orr D_0, D_0, C_0 - orr D_1, D_1, C_1 -L_update: - @ if A == 0: break - orrs ip, A_1, A_0 - beq L_exit - @ C >>= 1 - movs C_1, C_1, lsr #1 - movs C_0, C_0, rrx - @ if C == 0: break - orrs ip, C_1, C_0 - beq L_exit - @ B >>= 1 - movs B_1, B_1, lsr #1 - mov B_0, B_0, rrx - b L_subtract -L_exit: - @ Note: A, B & Q, R are aliases - mov R_0, A_0 - mov R_1, A_1 - mov Q_0, D_0 - mov Q_1, D_1 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_div_32_32: - @ Note: A_0 & r0 are aliases - @ Q_1 r1 - mov r1, B_0 - bl __aeabi_uidivmod - mov R_0, r1 - mov R_1, #0 - mov Q_1, #0 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_pow2: - @ Note: A, B and Q, R are aliases - @ R = A & (B - 1) - and C_0, A_0, C_0 - and C_1, A_1, C_1 - @ Q = A >> log2(B) - @ Note: B must not be 0 here! - clz D_0, B_0 - add D_1, D_0, #1 - rsbs D_0, D_0, #31 - bpl L_1 - clz D_0, B_1 - rsb D_0, D_0, #31 - mov A_0, A_1, lsr D_0 - add D_0, D_0, #32 -L_1: - movpl A_0, A_0, lsr D_0 - orrpl A_0, A_0, A_1, lsl D_1 - mov A_1, A_1, lsr D_0 - @ Mov back C to R - mov R_0, C_0 - mov R_1, C_1 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_div_by_0: - bl __div0 - @ As wrong as it could be - mov Q_0, #0 - mov Q_1, #0 - mov R_0, #0 - mov R_1, #0 - ldmfd sp!, {r4, r5, r6, r7, pc} diff --git a/src/arch/armv7/lib/div.c b/src/arch/armv7/lib/div.c deleted file mode 100644 index 03352dc..0000000 --- a/src/arch/armv7/lib/div.c +++ /dev/null @@ -1,5 +0,0 @@ -void __div0(void); // called from asm so no need for a prototype in a header -void __div0(void) -{ - // div by zero -} From gerrit at coreboot.org Fri Jan 4 21:22:09 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 21:22:09 +0100 Subject: [coreboot] Patch set updated for coreboot: efe3afe ARMv7: drop libgcc copy References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2102 -gerrit commit efe3afe4539917fa5620d0694db9fa1377e35973 Author: Stefan Reinauer Date: Fri Jan 4 12:10:28 2013 -0800 ARMv7: drop libgcc copy We accidently checked in some files from libgcc as well as a Makefile from u-boot and a duplicate implementation of div0. Drop all those files to reduce the confusion. Change-Id: I8ff6eabbced6f663813f8cc55f19c81839d03477 Signed-off-by: Stefan Reinauer --- src/arch/armv7/lib/Makefile.inc | 1 - src/arch/armv7/lib/Makefile.uboot | 95 ----------------------- src/arch/armv7/lib/_divsi3.S | 142 ---------------------------------- src/arch/armv7/lib/_udivsi3.S | 93 ---------------------- src/arch/armv7/lib/_uldivmod.S | 157 -------------------------------------- src/arch/armv7/lib/div.c | 5 -- 6 files changed, 493 deletions(-) diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc index bdf6a64..d911341 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -11,7 +11,6 @@ romstage-y += syslib.c ramstage-y += c_start.S -#ramstage-y += div.c ramstage-y += div0.c ramstage-y += div64.S ramstage-y += hang_spl.c diff --git a/src/arch/armv7/lib/Makefile.uboot b/src/arch/armv7/lib/Makefile.uboot deleted file mode 100644 index d33d08b..0000000 --- a/src/arch/armv7/lib/Makefile.uboot +++ /dev/null @@ -1,95 +0,0 @@ -# -# (C) Copyright 2002-2006 -# Wolfgang Denk, DENX Software Engineering, wd at denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB = $(obj)lib$(ARCH).o -LIBGCC = $(obj)libgcc.o - -ifndef CONFIG_SPL_BUILD -GLSOBJS += _ashldi3.o -GLSOBJS += _ashrdi3.o -GLSOBJS += _divsi3.o -GLSOBJS += _lshrdi3.o -GLSOBJS += _modsi3.o -GLSOBJS += _udivsi3.o -GLSOBJS += _umodsi3.o -ifdef CONFIG_CHROMEOS -GLSOBJS += _uldivmod.o -endif - -GLCOBJS += div0.o - -ifeq ($(CONFIG_SYS_GENERIC_BOARD),) -COBJS-y += board.o -endif -COBJS-y += bootm.o -COBJS-y += cache.o -COBJS-y += cache-cp15.o -COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o -SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o -SOBJS-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o -else # CONFIG_SPL_BUILD -ifeq ($(CONFIG_SYS_GENERIC_BOARD),) -COBJS-y += hang_spl.o -endif -endif # CONFIG_SPL_BUILD - -COBJS-y += interrupts.o -COBJS-y += reset.o - -SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \ - $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) -LGOBJS := $(addprefix $(obj),$(GLSOBJS)) \ - $(addprefix $(obj),$(GLCOBJS)) - -# Always build libarm.o -TARGETS := $(LIB) - -# Build private libgcc only when asked for -ifdef USE_PRIVATE_LIBGCC -TARGETS += $(LIBGCC) -endif - -# For EABI conformant tool chains, provide eabi_compat() -ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) -TARGETS += $(obj)eabi_compat.o -endif - -all: $(TARGETS) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -$(LIBGCC): $(obj).depend $(LGOBJS) - $(call cmd_link_o_target, $(LGOBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/src/arch/armv7/lib/_divsi3.S b/src/arch/armv7/lib/_divsi3.S deleted file mode 100644 index cfbadb2..0000000 --- a/src/arch/armv7/lib/_divsi3.S +++ /dev/null @@ -1,142 +0,0 @@ - -.macro ARM_DIV_BODY dividend, divisor, result, curbit - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \curbit, \divisor - clz \result, \dividend - sub \result, \curbit, \result - mov \curbit, #1 - mov \divisor, \divisor, lsl \result - mov \curbit, \curbit, lsl \result - mov \result, #0 - -#else - - @ Initially shift the divisor left 3 bits if possible, - @ set curbit accordingly. This allows for curbit to be located - @ at the left end of each 4 bit nibbles in the division loop - @ to save one loop in most cases. - tst \divisor, #0xe0000000 - moveq \divisor, \divisor, lsl #3 - moveq \curbit, #8 - movne \curbit, #1 - - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. -1: cmp \divisor, #0x10000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #4 - movlo \curbit, \curbit, lsl #4 - blo 1b - - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. -1: cmp \divisor, #0x80000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #1 - movlo \curbit, \curbit, lsl #1 - blo 1b - - mov \result, #0 - -#endif - - @ Division loop -1: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - orrhs \result, \result, \curbit - cmp \dividend, \divisor, lsr #1 - subhs \dividend, \dividend, \divisor, lsr #1 - orrhs \result, \result, \curbit, lsr #1 - cmp \dividend, \divisor, lsr #2 - subhs \dividend, \dividend, \divisor, lsr #2 - orrhs \result, \result, \curbit, lsr #2 - cmp \dividend, \divisor, lsr #3 - subhs \dividend, \dividend, \divisor, lsr #3 - orrhs \result, \result, \curbit, lsr #3 - cmp \dividend, #0 @ Early termination? - movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? - movne \divisor, \divisor, lsr #4 - bne 1b - -.endm - -.macro ARM_DIV2_ORDER divisor, order - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \order, \divisor - rsb \order, \order, #31 - -#else - - cmp \divisor, #(1 << 16) - movhs \divisor, \divisor, lsr #16 - movhs \order, #16 - movlo \order, #0 - - cmp \divisor, #(1 << 8) - movhs \divisor, \divisor, lsr #8 - addhs \order, \order, #8 - - cmp \divisor, #(1 << 4) - movhs \divisor, \divisor, lsr #4 - addhs \order, \order, #4 - - cmp \divisor, #(1 << 2) - addhi \order, \order, #3 - addls \order, \order, \divisor, lsr #1 - -#endif - -.endm - - .align 5 -.globl __divsi3 -.globl __aeabi_idiv -__divsi3: -__aeabi_idiv: - cmp r1, #0 - eor ip, r0, r1 @ save the sign of the result. - beq Ldiv0 - rsbmi r1, r1, #0 @ loops below use unsigned. - subs r2, r1, #1 @ division by 1 or -1 ? - beq 10f - movs r3, r0 - rsbmi r3, r0, #0 @ positive dividend value - cmp r3, r1 - bls 11f - tst r1, r2 @ divisor is power of 2 ? - beq 12f - - ARM_DIV_BODY r3, r1, r0, r2 - - cmp ip, #0 - rsbmi r0, r0, #0 - mov pc, lr - -10: teq ip, r0 @ same sign ? - rsbmi r0, r0, #0 - mov pc, lr - -11: movlo r0, #0 - moveq r0, ip, asr #31 - orreq r0, r0, #1 - mov pc, lr - -12: ARM_DIV2_ORDER r1, r2 - - cmp ip, #0 - mov r0, r3, lsr r2 - rsbmi r0, r0, #0 - mov pc, lr - -Ldiv0: - - str lr, [sp, #-4]! - bl __div0 - mov r0, #0 @ About as wrong as it could be. - ldr pc, [sp], #4 diff --git a/src/arch/armv7/lib/_udivsi3.S b/src/arch/armv7/lib/_udivsi3.S deleted file mode 100644 index 1309802..0000000 --- a/src/arch/armv7/lib/_udivsi3.S +++ /dev/null @@ -1,93 +0,0 @@ -/* # 1 "libgcc1.S" */ -@ libgcc1 routines for ARM cpu. -@ Division routines, written by Richard Earnshaw, (rearnsha at armltd.co.uk) -dividend .req r0 -divisor .req r1 -result .req r2 -curbit .req r3 -/* ip .req r12 */ -/* sp .req r13 */ -/* lr .req r14 */ -/* pc .req r15 */ - .text - .globl __udivsi3 - .type __udivsi3 ,function - .globl __aeabi_uidiv - .type __aeabi_uidiv ,function - .align 0 - __udivsi3: - __aeabi_uidiv: - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - mov result, #0 - cmp dividend, divisor - bcc Lgot_result -Loop1: - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. - cmp divisor, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 -Lbignum: - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. - cmp divisor, #0x80000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum -Loop3: - @ Test for possible subtractions, and note which bits - @ are done in the result. On the final pass, this may subtract - @ too much from the dividend, but the result will be ok, since the - @ "bit" will have been shifted out at the bottom. - cmp dividend, divisor - subcs dividend, dividend, divisor - orrcs result, result, curbit - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs result, result, curbit, lsr #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs result, result, curbit, lsr #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs result, result, curbit, lsr #3 - cmp dividend, #0 @ Early termination? - movnes curbit, curbit, lsr #4 @ No, any more bits to do? - movne divisor, divisor, lsr #4 - bne Loop3 -Lgot_result: - mov r0, result - mov pc, lr -Ldiv0: - str lr, [sp, #-4]! - bl __div0 (PLT) - mov r0, #0 @ about as wrong as it could be - ldmia sp!, {pc} - .size __udivsi3 , . - __udivsi3 - -.globl __aeabi_uidivmod -__aeabi_uidivmod: - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_uidiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -.globl __aeabi_idivmod -__aeabi_idivmod: - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_idiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr diff --git a/src/arch/armv7/lib/_uldivmod.S b/src/arch/armv7/lib/_uldivmod.S deleted file mode 100644 index 65e4fa8..0000000 --- a/src/arch/armv7/lib/_uldivmod.S +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - */ - -/* - * A, Q = r0 + (r1 << 32) - * B, R = r2 + (r3 << 32) - * A / B = Q ... R - */ - - .text - .global __aeabi_uldivmod - .type __aeabi_uldivmod, function - .align 0 - -A_0 .req r0 -A_1 .req r1 -B_0 .req r2 -B_1 .req r3 -C_0 .req r4 -C_1 .req r5 -D_0 .req r6 -D_1 .req r7 - -Q_0 .req r0 -Q_1 .req r1 -R_0 .req r2 -R_1 .req r3 - -__aeabi_uldivmod: - stmfd sp!, {r4, r5, r6, r7, lr} - @ Test if B == 0 - orrs ip, B_0, B_1 @ Z set -> B == 0 - beq L_div_by_0 - @ Test if B is power of 2: (B & (B - 1)) == 0 - subs C_0, B_0, #1 - sbc C_1, B_1, #0 - tst C_0, B_0 - tsteq B_1, C_1 - beq L_pow2 - @ Test if A_1 == B_1 == 0 - orrs ip, A_1, B_1 - beq L_div_32_32 - -L_div_64_64: - mov C_0, #1 - mov C_1, #0 - @ D_0 = clz A - teq A_1, #0 - clz D_0, A_1 - clzeq ip, A_0 - addeq D_0, D_0, ip - @ D_1 = clz B - teq B_1, #0 - clz D_1, B_1 - clzeq ip, B_0 - addeq D_1, D_1, ip - @ if clz B - clz A > 0 - subs D_0, D_1, D_0 - bls L_done_shift - @ B <<= (clz B - clz A) - subs D_1, D_0, #32 - rsb ip, D_0, #32 - movmi B_1, B_1, lsl D_0 - orrmi B_1, B_1, B_0, lsr ip - movpl B_1, B_0, lsl D_1 - mov B_0, B_0, lsl D_0 - @ C = 1 << (clz B - clz A) - movmi C_1, C_1, lsl D_0 - orrmi C_1, C_1, C_0, lsr ip - movpl C_1, C_0, lsl D_1 - mov C_0, C_0, lsl D_0 -L_done_shift: - mov D_0, #0 - mov D_1, #0 - @ C: current bit; D: result -L_subtract: - @ if A >= B - cmp A_1, B_1 - cmpeq A_0, B_0 - bcc L_update - @ A -= B - subs A_0, A_0, B_0 - sbc A_1, A_1, B_1 - @ D |= C - orr D_0, D_0, C_0 - orr D_1, D_1, C_1 -L_update: - @ if A == 0: break - orrs ip, A_1, A_0 - beq L_exit - @ C >>= 1 - movs C_1, C_1, lsr #1 - movs C_0, C_0, rrx - @ if C == 0: break - orrs ip, C_1, C_0 - beq L_exit - @ B >>= 1 - movs B_1, B_1, lsr #1 - mov B_0, B_0, rrx - b L_subtract -L_exit: - @ Note: A, B & Q, R are aliases - mov R_0, A_0 - mov R_1, A_1 - mov Q_0, D_0 - mov Q_1, D_1 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_div_32_32: - @ Note: A_0 & r0 are aliases - @ Q_1 r1 - mov r1, B_0 - bl __aeabi_uidivmod - mov R_0, r1 - mov R_1, #0 - mov Q_1, #0 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_pow2: - @ Note: A, B and Q, R are aliases - @ R = A & (B - 1) - and C_0, A_0, C_0 - and C_1, A_1, C_1 - @ Q = A >> log2(B) - @ Note: B must not be 0 here! - clz D_0, B_0 - add D_1, D_0, #1 - rsbs D_0, D_0, #31 - bpl L_1 - clz D_0, B_1 - rsb D_0, D_0, #31 - mov A_0, A_1, lsr D_0 - add D_0, D_0, #32 -L_1: - movpl A_0, A_0, lsr D_0 - orrpl A_0, A_0, A_1, lsl D_1 - mov A_1, A_1, lsr D_0 - @ Mov back C to R - mov R_0, C_0 - mov R_1, C_1 - ldmfd sp!, {r4, r5, r6, r7, pc} - -L_div_by_0: - bl __div0 - @ As wrong as it could be - mov Q_0, #0 - mov Q_1, #0 - mov R_0, #0 - mov R_1, #0 - ldmfd sp!, {r4, r5, r6, r7, pc} diff --git a/src/arch/armv7/lib/div.c b/src/arch/armv7/lib/div.c deleted file mode 100644 index 03352dc..0000000 --- a/src/arch/armv7/lib/div.c +++ /dev/null @@ -1,5 +0,0 @@ -void __div0(void); // called from asm so no need for a prototype in a header -void __div0(void) -{ - // div by zero -} From gerrit at coreboot.org Fri Jan 4 21:22:09 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 21:22:09 +0100 Subject: [coreboot] Patch set updated for coreboot: 6d2a96a armv7: invoke intermediate build rules References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit 6d2a96a7fc49be322082be8c46dfdfcbe55a8f53 Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 9bca71c..7b6a120 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Fri Jan 4 21:22:10 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 21:22:10 +0100 Subject: [coreboot] New patch to review for coreboot: 516ec9f ARMv7: Make ABI compatible to reference toolchain References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2103 -gerrit commit 516ec9fc1c6ab825b2301b6f75b602f1b83d8539 Author: Stefan Reinauer Date: Fri Jan 4 12:19:23 2013 -0800 ARMv7: Make ABI compatible to reference toolchain Our reference toolchain uses -mabi=aapcs whereas we started forcing -mabi=aapcs-linux. Drop this to prevent ABI incompatibility. Also drop -fno-common since that's set in the top level Makefile.inc already. Change-Id: I4afdcf5da9a5d86c2f9e5de5c7d523ccd2f5f1e0 Signed-off-by: Stefan Reinauer --- src/arch/armv7/Makefile.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 9e57244..9bca71c 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -139,9 +139,7 @@ endif # done CFLAGS += \ - -fno-common\ -ffixed-r8\ - -mabi=aapcs-linux\ -march=armv7-a\ -marm\ -mno-unaligned-access\ From gerrit at coreboot.org Fri Jan 4 22:13:44 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 22:13:44 +0100 Subject: [coreboot] Patch merged into coreboot/master: 3a8badc ARMv7: drop libgcc copy References: Message-ID: the following patch was just integrated into master: commit 3a8badc26519cd900d4f01c87c212973a1aea00c Author: Stefan Reinauer Date: Fri Jan 4 12:10:28 2013 -0800 ARMv7: drop libgcc copy We accidently checked in some files from libgcc as well as a Makefile from u-boot and a duplicate implementation of div0. Drop all those files to reduce the confusion. Change-Id: I8ff6eabbced6f663813f8cc55f19c81839d03477 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2102 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Fri Jan 4 21:37:57 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 22:13:43 2013, giving +2 See http://review.coreboot.org/2102 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 22:14:20 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 22:14:20 +0100 Subject: [coreboot] Patch merged into coreboot/master: 853f469 ARMv7: Make ABI compatible to reference toolchain References: Message-ID: the following patch was just integrated into master: commit 853f4698a8ef9366178b83b0c42a3f662dc45c95 Author: Stefan Reinauer Date: Fri Jan 4 12:19:23 2013 -0800 ARMv7: Make ABI compatible to reference toolchain Our reference toolchain uses -mabi=aapcs whereas we started forcing -mabi=aapcs-linux. Drop this to prevent ABI incompatibility. Also drop -fno-common since that's set in the top level Makefile.inc already. Change-Id: I4afdcf5da9a5d86c2f9e5de5c7d523ccd2f5f1e0 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2103 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Fri Jan 4 21:55:31 2013, giving +1 Reviewed-By: Ronald G. Minnich at Fri Jan 4 22:14:19 2013, giving +2 See http://review.coreboot.org/2103 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 22:17:40 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Fri, 4 Jan 2013 22:17:40 +0100 Subject: [coreboot] New patch to review for coreboot: 8cec335 Revert "armv7: pass bootblock offset from Kconfig into cbfstool" References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2104 -gerrit commit 8cec3356101932a414ea87bce317107f8f65675f Author: Ronald G. Minnich Date: Fri Jan 4 22:17:38 2013 +0100 Revert "armv7: pass bootblock offset from Kconfig into cbfstool" This reverts commit ec8d35fe911ab35a5f40fd5b452f5463857b244a We are almost certain that this is not necessary. Change-Id: I70e94f883be95655da00a0b127ed9ffd7c81c63b --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 245cd8a..1a1271f 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -49,7 +49,7 @@ prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) $(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \ -B $(objcbfs)/bootblock.bin -a 64 \ - -o $(CONFIG_BOOTBLOCK_OFFSET) + -o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) )) $(prebuild-files) true mv $@.tmp $@ else From gerrit at coreboot.org Fri Jan 4 22:50:44 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Fri, 4 Jan 2013 22:50:44 +0100 Subject: [coreboot] New patch to review for coreboot: 4106b20 Flatten the tree References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2105 -gerrit commit 4106b20b2ca84293812959c8a0aa45f15fe039c7 Author: Ronald G. Minnich Date: Fri Jan 4 13:50:00 2013 -0800 Flatten the tree It makes no sense to have directories with one file. Change-Id: I65ba93dda5e6a4bcc5a7cc049c1378ebf5d6abcd Signed-off-by: Ronald G. Minnich --- src/arch/armv7/Makefile.inc | 2 +- src/arch/armv7/init.S | 94 +++++++++++++++++++++++++++++++++++++++++++++ src/arch/armv7/init/init.S | 94 --------------------------------------------- 3 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 9bca71c..5b29616 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -150,7 +150,7 @@ CFLAGS += \ CFLAGS += -D__KERNEL__ CFLAGS += -D__LINUX_ARM_ARCH__=7 -crt0s = $(src)/arch/armv7/init/init.S +crt0s = $(src)/arch/armv7/init.S ldscripts = ldscripts += $(src)/arch/armv7/romstage.ld diff --git a/src/arch/armv7/init.S b/src/arch/armv7/init.S new file mode 100644 index 0000000..033637e --- /dev/null +++ b/src/arch/armv7/init.S @@ -0,0 +1,94 @@ +/* + * Early initialization code for ARMv7 architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gr?ger + * Copyright (c) 2002 Alex Z?pke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define __ASSEMBLY__ +#include + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq +_undefined_instruction: .word _undefined_instruction +_software_interrupt: .word _software_interrupt +_prefetch_abort: .word _prefetch_abort +_data_abort: .word _data_abort +_not_used: .word _not_used +_irq: .word _irq +_fiq: .word _fiq +_pad: .word 0x12345678 /* now 16*4=64 */ + + .balignl 16,0xdeadbeef + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr,r0 + + /* + * From Cortex-A Series Programmer's Guide: + * Only CPU 0 performs initialization. Other CPUs go into WFI + * to do this, first work out which CPU this is + * this code typically is run before any other initialization step + */ + mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register + and r1, r1, #0x3 @ Extract CPU ID bits + cmp r1, #0 + bne wait_for_interrupt @ If this is not core0, wait + + /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ + mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register + bic r0, #CR_V @ V = 0 + mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register + + /* Set vector address in CP15 VBAR register */ + ldr r0, =_start + mcr p15, 0, r0, c12, c0, 0 @Set VBAR + +/* Set stackpointer in internal RAM to call board_init_f */ +call_board_init_f: + ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) + mov sp, r0 + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr r0,=0x00000000 + bl board_init_f + +wait_for_interrupt: + wfi + mov pc, lr @ back to my caller diff --git a/src/arch/armv7/init/init.S b/src/arch/armv7/init/init.S deleted file mode 100644 index 033637e..0000000 --- a/src/arch/armv7/init/init.S +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Early initialization code for ARMv7 architecture. - * - * This file is based off of the OMAP3530/ARM Cortex start.S file from Das - * U-Boot, which itself got the file from armboot. - * - * Copyright (c) 2004 Texas Instruments - * Copyright (c) 2001 Marius Gr?ger - * Copyright (c) 2002 Alex Z?pke - * Copyright (c) 2002 Gary Jennejohn - * Copyright (c) 2003 Richard Woodruff - * Copyright (c) 2003 Kshitij - * Copyright (c) 2006-2008 Syed Mohammed Khasim - * Copyright (c) 2013 The Chromium OS Authors - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#define __ASSEMBLY__ -#include - -.globl _start -_start: b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq -_undefined_instruction: .word _undefined_instruction -_software_interrupt: .word _software_interrupt -_prefetch_abort: .word _prefetch_abort -_data_abort: .word _data_abort -_not_used: .word _not_used -_irq: .word _irq -_fiq: .word _fiq -_pad: .word 0x12345678 /* now 16*4=64 */ - - .balignl 16,0xdeadbeef - -reset: - /* - * set the cpu to SVC32 mode - */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - msr cpsr,r0 - - /* - * From Cortex-A Series Programmer's Guide: - * Only CPU 0 performs initialization. Other CPUs go into WFI - * to do this, first work out which CPU this is - * this code typically is run before any other initialization step - */ - mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register - and r1, r1, #0x3 @ Extract CPU ID bits - cmp r1, #0 - bne wait_for_interrupt @ If this is not core0, wait - - /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ - mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register - bic r0, #CR_V @ V = 0 - mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register - - /* Set vector address in CP15 VBAR register */ - ldr r0, =_start - mcr p15, 0, r0, c12, c0, 0 @Set VBAR - -/* Set stackpointer in internal RAM to call board_init_f */ -call_board_init_f: - ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) - mov sp, r0 - bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ - ldr r0,=0x00000000 - bl board_init_f - -wait_for_interrupt: - wfi - mov pc, lr @ back to my caller From gerrit at coreboot.org Fri Jan 4 22:54:02 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Fri, 4 Jan 2013 22:54:02 +0100 Subject: [coreboot] New patch to review for coreboot: a1ebc64 cbfstool: Fix warnings on OS X References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2106 -gerrit commit a1ebc64f885b4ab0648e8743e994e8b835169ee5 Author: Stefan Reinauer Date: Fri Jan 4 13:51:36 2013 -0800 cbfstool: Fix warnings on OS X Most hton and noth functions are already available through the system headers we include on OS X, causing the compiler to warn about duplicate definitions. Change-Id: Id81852dfc028cf0c48155048c54d431436889c0e Signed-off-by: Stefan Reinauer --- util/cbfstool/common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index b5258a3..853e529 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -22,8 +22,10 @@ #include #include "swab.h" +#ifndef __APPLE__ #define ntohl(x) (host_bigendian?(x):swab32(x)) #define htonl(x) (host_bigendian?(x):swab32(x)) +#endif #define ntohll(x) (host_bigendian?(x):swab64(x)) #define htonll(x) (host_bigendian?(x):swab64(x)) From gerrit at coreboot.org Fri Jan 4 23:11:28 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 23:11:28 +0100 Subject: [coreboot] Patch merged into coreboot/master: fa60de9 Revert "armv7: pass bootblock offset from Kconfig into cbfstool" References: Message-ID: the following patch was just integrated into master: commit fa60de996d7c9676cf219c90e3cff602e148468d Author: Ronald G. Minnich Date: Fri Jan 4 22:17:38 2013 +0100 Revert "armv7: pass bootblock offset from Kconfig into cbfstool" This reverts commit ec8d35fe911ab35a5f40fd5b452f5463857b244a We are almost certain that this is not necessary. Change-Id: I70e94f883be95655da00a0b127ed9ffd7c81c63b Reviewed-on: http://review.coreboot.org/2104 Reviewed-by: Stefan Reinauer Reviewed-by: David Hendricks Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Fri Jan 4 22:39:52 2013, giving +1 Reviewed-By: Stefan Reinauer at Fri Jan 4 22:18:39 2013, giving +2 See http://review.coreboot.org/2104 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 23:12:51 2013 From: gerrit at coreboot.org (Ronald G. Minnich (rminnich@gmail.com)) Date: Fri, 4 Jan 2013 23:12:51 +0100 Subject: [coreboot] New patch to review for coreboot: 3dd53c5 Make room for cbfs header in the build. References: Message-ID: Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2107 -gerrit commit 3dd53c550020bd0c85ba535ae59e70ff8b8399db Author: Ronald G. Minnich Date: Fri Jan 4 14:12:09 2013 -0800 Make room for cbfs header in the build. cbfstool can either blindly write the header at start of image + 16, or look for deadbeef (and skip badbeef) Change-Id: Iee7ed65170fdf96488d9740c1342305ff13e52de Signed-off-by: Ronald G. Minnich --- src/arch/armv7/init.S | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/arch/armv7/init.S b/src/arch/armv7/init.S index 033637e..83e06c4 100644 --- a/src/arch/armv7/init.S +++ b/src/arch/armv7/init.S @@ -34,24 +34,12 @@ .globl _start _start: b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq -_undefined_instruction: .word _undefined_instruction -_software_interrupt: .word _software_interrupt -_prefetch_abort: .word _prefetch_abort -_data_abort: .word _data_abort -_not_used: .word _not_used -_irq: .word _irq -_fiq: .word _fiq -_pad: .word 0x12345678 /* now 16*4=64 */ - - .balignl 16,0xdeadbeef - + .balignl 16, 0xbadbeef + /* here is where cbfstool will put the cbfs master header */ +_cbfs: .word 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef + .word 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef + .word 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef + .word 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef reset: /* * set the cpu to SVC32 mode From gerrit at coreboot.org Fri Jan 4 23:24:16 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 23:24:16 +0100 Subject: [coreboot] Patch merged into coreboot/master: 2485df3 Flatten the tree References: Message-ID: the following patch was just integrated into master: commit 2485df3897d4254cbec6fd24a768c38149c69a36 Author: Ronald G. Minnich Date: Fri Jan 4 13:50:00 2013 -0800 Flatten the tree It makes no sense to have directories with one file. Change-Id: I65ba93dda5e6a4bcc5a7cc049c1378ebf5d6abcd Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/2105 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks Build-Tested: build bot (Jenkins) at Fri Jan 4 23:11:14 2013, giving +1 Reviewed-By: David Hendricks at Fri Jan 4 23:20:04 2013, giving +2 See http://review.coreboot.org/2105 for details. -gerrit From gerrit at coreboot.org Fri Jan 4 23:29:39 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Fri, 4 Jan 2013 23:29:39 +0100 Subject: [coreboot] Patch merged into coreboot/master: 9da7570 cbfstool: Fix warnings on OS X References: Message-ID: the following patch was just integrated into master: commit 9da7570b07abd99123afc0e95a72a6bb0dcbddf5 Author: Stefan Reinauer Date: Fri Jan 4 13:51:36 2013 -0800 cbfstool: Fix warnings on OS X Most hton and noth functions are already available through the system headers we include on OS X, causing the compiler to warn about duplicate definitions. Change-Id: Id81852dfc028cf0c48155048c54d431436889c0e Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2106 Reviewed-by: Ronald G. Minnich Reviewed-by: David Hendricks Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Fri Jan 4 23:24:56 2013, giving +1 See http://review.coreboot.org/2106 for details. -gerrit From gerrit at coreboot.org Sat Jan 5 00:03:24 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Sat, 5 Jan 2013 00:03:24 +0100 Subject: [coreboot] New patch to review for coreboot: 4cfb3d8 ARMv7: drop __KERNEL__ References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2108 -gerrit commit 4cfb3d80c413adbc7cfffceba4ab5a44907d45ca Author: Stefan Reinauer Date: Fri Jan 4 15:02:25 2013 -0800 ARMv7: drop __KERNEL__ It's a bad Linux heritage.. We have no userland in firmware. Change-Id: Ib19e5ba713078ca37514571213d19f418417b964 Signed-off-by: Stefan Reinauer --- src/arch/armv7/Makefile.inc | 1 - src/arch/armv7/include/arch/atomic.h | 111 ----------------------------------- src/arch/armv7/include/arch/io.h | 6 -- src/arch/armv7/include/arch/types.h | 7 --- 4 files changed, 125 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index fcb6a17..d7fbbdf 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -147,7 +147,6 @@ CFLAGS += \ -mthumb-interwork # For various headers imported from Linux -CFLAGS += -D__KERNEL__ CFLAGS += -D__LINUX_ARM_ARCH__=7 crt0s = $(src)/arch/armv7/init.S diff --git a/src/arch/armv7/include/arch/atomic.h b/src/arch/armv7/include/arch/atomic.h deleted file mode 100644 index 5a8954f..0000000 --- a/src/arch/armv7/include/arch/atomic.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * linux/include/asm-arm/atomic.h - * - * Copyright (c) 1996 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 27-06-1996 RMK Created - * 13-04-1997 RMK Made functions atomic! - * 07-12-1997 RMK Upgraded for v2.1. - * 26-08-1998 PJB Added #ifdef __KERNEL__ - */ -#ifndef __ASM_ARM_ATOMIC_H -#define __ASM_ARM_ATOMIC_H - -#include - -#ifdef CONFIG_SMP -#error SMP not supported -#endif - -typedef struct { volatile int counter; } atomic_t; - -#define ATOMIC_INIT(i) { (i) } - -#include - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) - -static inline void atomic_add(int i, volatile atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - v->counter += i; - local_irq_restore(flags); -} - -static inline void atomic_sub(int i, volatile atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - v->counter -= i; - local_irq_restore(flags); -} - -static inline void atomic_inc(volatile atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - v->counter += 1; - local_irq_restore(flags); -} - -static inline void atomic_dec(volatile atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - v->counter -= 1; - local_irq_restore(flags); -} - -static inline int atomic_dec_and_test(volatile atomic_t *v) -{ - unsigned long flags; - int val; - - local_irq_save(flags); - val = v->counter; - v->counter = val -= 1; - local_irq_restore(flags); - - return val == 0; -} - -static inline int atomic_add_negative(int i, volatile atomic_t *v) -{ - unsigned long flags; - int val; - - local_irq_save(flags); - val = v->counter; - v->counter = val += i; - local_irq_restore(flags); - - return val < 0; -} - -static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) -{ - unsigned long flags; - - local_irq_save(flags); - *addr &= ~mask; - local_irq_restore(flags); -} - -/* Atomic operations are already serializing on ARM */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#endif diff --git a/src/arch/armv7/include/arch/io.h b/src/arch/armv7/include/arch/io.h index 7675a88..3bbd529 100644 --- a/src/arch/armv7/include/arch/io.h +++ b/src/arch/armv7/include/arch/io.h @@ -20,13 +20,8 @@ #ifndef __ASM_ARM_IO_H #define __ASM_ARM_IO_H -#ifdef __KERNEL__ - #include #include -#if 0 /* XXX###XXX */ -#include -#endif /* XXX###XXX */ static inline void sync(void) { @@ -423,5 +418,4 @@ out: #define isa_check_signature(io,sig,len) (0) #endif /* __mem_isa */ -#endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/src/arch/armv7/include/arch/types.h b/src/arch/armv7/include/arch/types.h index 71dc049..be7e76c 100644 --- a/src/arch/armv7/include/arch/types.h +++ b/src/arch/armv7/include/arch/types.h @@ -22,11 +22,6 @@ __extension__ typedef __signed__ long long __s64; __extension__ typedef unsigned long long __u64; #endif -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - typedef signed char s8; typedef unsigned char u8; @@ -48,6 +43,4 @@ typedef u32 dma_addr_t; typedef unsigned long phys_addr_t; typedef unsigned long phys_size_t; -#endif /* __KERNEL__ */ - #endif From gerrit at coreboot.org Sat Jan 5 00:32:14 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Sat, 5 Jan 2013 00:32:14 +0100 Subject: [coreboot] Patch merged into coreboot/master: 6d47cbe ARMv7: drop __KERNEL__ References: Message-ID: the following patch was just integrated into master: commit 6d47cbe75859eaca4d56dd371d9dee6bd75dd23d Author: Stefan Reinauer Date: Fri Jan 4 15:02:25 2013 -0800 ARMv7: drop __KERNEL__ It's a bad Linux heritage.. We have no userland in firmware. Change-Id: Ib19e5ba713078ca37514571213d19f418417b964 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2108 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Sat Jan 5 00:10:55 2013, giving +1 Reviewed-By: Ronald G. Minnich at Sat Jan 5 00:32:13 2013, giving +2 See http://review.coreboot.org/2108 for details. -gerrit From ajg4tadpole at gmail.com Sat Jan 5 00:23:04 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Fri, 04 Jan 2013 23:23:04 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: <50E76458.8060401@gmail.com> On 02/01/13 19:28, David Hubbard wrote: > Andrew, Ron, what's your take on http://mjg59.dreamwidth.org/20916.html ? > > Specifically: > "This is part of Windows 8's fast boot support - the keyboard may not be > initialised until after the OS has started." OK, the feature is deferred initialisation of USB devices until they are actually needed. Windows 8 is making use of this but it is introduced as part of the UEFI spec 2.3.1c. This is optional to implement it or not, OEM gets to decide. This is in the UEFI spec and can be used by other OSes than Windows eg Grub could use it to speed up loading of Linux. > 4. User is thus *forced* to use Win8's "hold down shift and restart" > feature -- adding another barrier before a user can boot her own OS. > > I think the biggest problem here is that the entire BIOS is made > inaccessible, and only if Windows gives permission can you change that. Well yes and no. 1) PS/2 keyboards are not affected, they are still initialised and available as normal. Many laptop keyboards are implemented as PS/2 devices. 2) There are a number of ways that you can get USB enumerated and keyboards initialised. a) If HDD is not primary boot target b) If primary boot target fails c) If bootloader invokes EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. ReadKeyStrokeEx() So yes, on a motherboard that implements it, with no PS/2 keyboard, with the HDD as primary boot target and with Win8 installed then you may have to use the Win8 menu to restart into the UEFI settings screens. And yes this can be a small barrier to booting using an alternative method for any reason, not just installing an alternative OS. But quite frankly I have seen some bizarre setup screens on legacy BIOS that made choosing to boot from a USB device an exercise in frustration. So this extra step in the road to booting an alternate OS is not that big a deal. It can at least be documented and is not a hard thing to do at all. Even without this there are some machines that boot so fast it is not easy to press the key to get to the setup screens at the right time, this may actually give a more reliable way to get to the setup screens on those machines. > Regards, > David BTW 1) when you use BIOS above, you actually mean Setup. Setup is an application launched by the BIOS to view or change system settings. The BIOS is not accessible nor inaccessible, it is running as soon as the CPU begins to execute code and will complete its tasks as normal according to those system settings. BTW 2) its UEFI firmware, not BIOS. Just as coreboot is not BIOS. Best wishes, Andrew From ajg4tadpole at gmail.com Sat Jan 5 00:41:37 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Fri, 04 Jan 2013 23:41:37 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: <50E768B1.50903@gmail.com> On 03/01/13 18:40, ron minnich wrote: > OK, after further thought, here's my take. > > Two companies have defined a secure boot standard in such a way that > they can closely control what boots on future systems using the one > company's chips. This is a sea change from the original IBM PC design, > which encouraged people to boot anything, and included the > (copyrighted) BIOS listing on paper to further that end. OK, then there was a simple source listing so you could see what the code provided in terms of functionality and then implement that functionality. Now you have the UEFI spec so you can implement the required functionality. There is nothing specific to those companies here. Yes Secure Boot makes it harder to change the OS shipped on any particular machine and bugs or deficiencies may even make it impossible in some cases. But given the goal of only running authorised code then this is inevitable. > The current state is that the software company is becoming the > gatekeeper for what OS will run on systems built using the hardware > company's chips. Their end goal is that the software company becomes > the gatekeeper for what runs on almost *anything* -- not just x86. > Don't believe me? Read about ARM systems and Windows 8. I have yet to see Linux or Android on an iPad. WinRT (not Win8) on ARM is little different, if at all. It will have no effect whatsoever on other tablets. They do not control all ARM tablets and never will. Andrew From rminnich at gmail.com Sat Jan 5 00:52:43 2013 From: rminnich at gmail.com (ron minnich) Date: Fri, 4 Jan 2013 15:52:43 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E768B1.50903@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E768B1.50903@gmail.com> Message-ID: On Fri, Jan 4, 2013 at 3:41 PM, Andrew Goodbody wrote: > > Now you have the UEFI spec so you can implement the required functionality. I can only hope you're joking. ron From ajg4tadpole at gmail.com Sat Jan 5 01:03:04 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Sat, 05 Jan 2013 00:03:04 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: <50E76DB8.7030507@gmail.com> On 03/01/13 23:23, gary sheppard wrote: > Numerous security experts have already said it is anything but secure, > and it will never be secure. They have only said this quietly, and that > "voice" has been minimalized, while "PROGRESS" is shouted to the > heavens. Hey, look at android and how phone makers "lock" it down. Does > it stay locked? No! Come on people, put your heads out of... ;) > > Gary Security is not an absolute. It is a tradeoff against the time needed to overcome it. Secure Boot is more secure than no security. coreboot offers no security. coreboot can never be "the Solution to the Secure Boot Fiasco" until it can offer better security than Secure Boot. Yes there may be breaks for early implementations of Secure Boot but anyone predicting that it can never be fixed is a very brave person. Never is a long time. Remember, fixed does not mean perfect. Fixed just means takes longer to overcome than anyone cares to invest in it. Sorry but "this will be broken because everything before it has been broken" is not a credible critique; that is the inductive fallacy. Andrew From gerrit at coreboot.org Sat Jan 5 01:06:47 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Sat, 5 Jan 2013 01:06:47 +0100 Subject: [coreboot] New patch to review for coreboot: fd7e1b9 Update 3rdparty mark to latest repository References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2110 -gerrit commit fd7e1b946ef7b825c2b4f644538663fda19cb805 Author: Stefan Reinauer Date: Fri Jan 4 16:04:34 2013 -0800 Update 3rdparty mark to latest repository Change-Id: I59fca4427345c7e677138b944613a1554d5a8331 Signed-off-by: Stefan Reinauer --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index 7eb78b1..4c0dcf9 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 7eb78b1109242653c60cccd741951dcb58f51cec +Subproject commit 4c0dcf96ae73ba31bf9aa689768a5ecd47bac19e From ajg4tadpole at gmail.com Sat Jan 5 01:09:12 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Sat, 05 Jan 2013 00:09:12 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> Message-ID: <50E76F28.9030605@gmail.com> On 04/01/13 02:54, David Hubbard wrote: > I personally use > Gentoo Linux which means my kernels are compiled right on my own box. > Secure Boot will never work for that (specifically, getting each kernel > signed for each user would never scale). Enrol your own key. Sign your own kernel. Seems to scale linearly per user to me. Security is not free. There will always be a cost. Andrew From rminnich at gmail.com Sat Jan 5 01:10:04 2013 From: rminnich at gmail.com (ron minnich) Date: Fri, 4 Jan 2013 16:10:04 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E76DB8.7030507@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> Message-ID: Actually, there is an open source secure boot being sold now that allows people the option of bypassing it, and booting anything they want. These systems are based on U-boot and coreboot. Andrew, so far, I don't find your arguments very convincing. ron From ajg4tadpole at gmail.com Sat Jan 5 01:29:51 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Sat, 05 Jan 2013 00:29:51 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> Message-ID: <50E773FF.4010401@gmail.com> On 05/01/13 00:10, ron minnich wrote: > Andrew, so far, I don't find your arguments very convincing. Can you explain to me why Intel would want to control what OS is run on their chipsets? Intel are an active contributor to the Linux kernel for their display drivers. Andrew From gerrit at coreboot.org Sat Jan 5 01:30:47 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Sat, 5 Jan 2013 01:30:47 +0100 Subject: [coreboot] New patch to review for coreboot: 6fa27b8 ARMv7: drop __ASSEMBLY__ References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2111 -gerrit commit 6fa27b85b7c766d7901e28d5ad014bba499e33b7 Author: Stefan Reinauer Date: Fri Jan 4 16:29:29 2013 -0800 ARMv7: drop __ASSEMBLY__ We moved to using __ASSEMBLER__ years ago since it is set by as. Change-Id: I60103ba23ebe87be1d0bc63beed0ef5b05eed4f2 Signed-off-by: Stefan Reinauer --- src/arch/armv7/include/system.h | 2 +- src/arch/armv7/init.S | 1 - src/arch/armv7/start.S | 1 - src/cpu/samsung/exynos5-common/adc.h | 2 +- src/cpu/samsung/exynos5-common/gpio.h | 2 +- src/cpu/samsung/exynos5-common/mmc.h | 4 ++-- src/cpu/samsung/exynos5-common/mshc.h | 2 +- src/cpu/samsung/exynos5-common/pwm.h | 4 ++-- src/cpu/samsung/exynos5-common/spi.h | 4 ++-- src/cpu/samsung/exynos5-common/sromc.h | 4 ++-- src/cpu/samsung/exynos5-common/watchdog.h | 4 ++-- src/cpu/samsung/exynos5250/cpu.h | 2 +- src/cpu/samsung/exynos5250/spi.h | 4 ++-- src/cpu/samsung/s5p-common/clock.h | 2 +- src/cpu/samsung/s5p-common/gpio.h | 2 +- src/cpu/samsung/s5p-common/mmc.h | 4 ++-- src/cpu/samsung/s5p-common/pwm.h | 4 ++-- src/cpu/samsung/s5p-common/sromc.h | 4 ++-- src/cpu/samsung/s5p-common/uart.h | 4 ++-- src/cpu/samsung/s5p-common/watchdog.h | 4 ++-- 20 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/arch/armv7/include/system.h b/src/arch/armv7/include/system.h index 3e14fdb..c74ce8c 100644 --- a/src/arch/armv7/include/system.h +++ b/src/arch/armv7/include/system.h @@ -60,7 +60,7 @@ #define arch_align_stack(x) (x) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ static inline unsigned int get_cr(void) { unsigned int val; diff --git a/src/arch/armv7/init.S b/src/arch/armv7/init.S index 033637e..7848581 100644 --- a/src/arch/armv7/init.S +++ b/src/arch/armv7/init.S @@ -29,7 +29,6 @@ * MA 02111-1307 USA */ -#define __ASSEMBLY__ #include .globl _start diff --git a/src/arch/armv7/start.S b/src/arch/armv7/start.S index 63cac4b..8af48eb 100644 --- a/src/arch/armv7/start.S +++ b/src/arch/armv7/start.S @@ -29,7 +29,6 @@ * MA 02111-1307 USA */ -#define __ASSEMBLY__ #include .globl _start diff --git a/src/cpu/samsung/exynos5-common/adc.h b/src/cpu/samsung/exynos5-common/adc.h index dc905d1..64f4813 100644 --- a/src/cpu/samsung/exynos5-common/adc.h +++ b/src/cpu/samsung/exynos5-common/adc.h @@ -25,7 +25,7 @@ #ifndef __ASM_ARM_ARCH_COMMON_ADC_H_ #define __ASM_ARM_ARCH_COMMON_ADC_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_adc { unsigned int adccon; unsigned int adctsc; diff --git a/src/cpu/samsung/exynos5-common/gpio.h b/src/cpu/samsung/exynos5-common/gpio.h index 37dd678..d291fae 100644 --- a/src/cpu/samsung/exynos5-common/gpio.h +++ b/src/cpu/samsung/exynos5-common/gpio.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_COMMON_GPIO_H #define __ASM_ARCH_COMMON_GPIO_H -#ifndef __ASSEMBLY__ /* FIXME: not needed (i hope)? */ +#ifndef __ASSEMBLER__ /* FIXME: not needed (i hope)? */ #include /* FIXME: s5p's gpio.h and exynos' gpio.h have a lot of conflicting definitions */ diff --git a/src/cpu/samsung/exynos5-common/mmc.h b/src/cpu/samsung/exynos5-common/mmc.h index 4e43589..f607f82 100644 --- a/src/cpu/samsung/exynos5-common/mmc.h +++ b/src/cpu/samsung/exynos5-common/mmc.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_COMMON_MMC_H_ #define __ASM_ARCH_COMMON_MMC_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_mmc { unsigned int sysad; unsigned short blksize; @@ -73,5 +73,5 @@ int s5p_mmc_init(const void *blob); int s5p_mmc_init(int dev_index, int bus_width); #endif -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5-common/mshc.h b/src/cpu/samsung/exynos5-common/mshc.h index bdb0a9c..623492c 100644 --- a/src/cpu/samsung/exynos5-common/mshc.h +++ b/src/cpu/samsung/exynos5-common/mshc.h @@ -21,7 +21,7 @@ #define __ASM_ARCH_COMMON_MSHC_H #include -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct mshci_host { struct s5p_mshci *reg; /* Mapped address */ unsigned int clock; /* Current clock in MHz */ diff --git a/src/cpu/samsung/exynos5-common/pwm.h b/src/cpu/samsung/exynos5-common/pwm.h index e35d88d..a4e0acf 100644 --- a/src/cpu/samsung/exynos5-common/pwm.h +++ b/src/cpu/samsung/exynos5-common/pwm.h @@ -42,7 +42,7 @@ #define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) #define TCON4_AUTO_RELOAD (1 << 22) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_timer { unsigned int tcfg0; unsigned int tcfg1; @@ -63,6 +63,6 @@ struct s5p_timer { unsigned int tcnto4; unsigned int tintcstat; }; -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5-common/spi.h b/src/cpu/samsung/exynos5-common/spi.h index 3430ac1..3f36759 100644 --- a/src/cpu/samsung/exynos5-common/spi.h +++ b/src/cpu/samsung/exynos5-common/spi.h @@ -20,7 +20,7 @@ #ifndef __ASM_ARCH_EXYNOS_COMMON_SPI_H_ #define __ASM_ARCH_EXYNOS_COMMON_SPI_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* SPI peripheral register map; padded to 64KB */ struct exynos_spi { @@ -85,5 +85,5 @@ struct exynos_spi { #define SPI_RX_BYTE_SWAP (1 << 6) #define SPI_RX_HWORD_SWAP (1 << 7) -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5-common/sromc.h b/src/cpu/samsung/exynos5-common/sromc.h index b413373..d4fdae9 100644 --- a/src/cpu/samsung/exynos5-common/sromc.h +++ b/src/cpu/samsung/exynos5-common/sromc.h @@ -38,12 +38,12 @@ #define SROMC_BC_TACP(x) (x << 4) /* page mode access cycle */ #define SROMC_BC_PMC(x) (x << 0) /* normal(1data)page mode configuration */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_sromc { unsigned int bw; unsigned int bc[4]; }; -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ /* Configure the Band Width and Bank Control Regs for required SROMC Bank */ void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf); diff --git a/src/cpu/samsung/exynos5-common/watchdog.h b/src/cpu/samsung/exynos5-common/watchdog.h index af98638..5b3b651 100644 --- a/src/cpu/samsung/exynos5-common/watchdog.h +++ b/src/cpu/samsung/exynos5-common/watchdog.h @@ -41,7 +41,7 @@ #define WTCON_RESET (0x1 << WTCON_RESET_OFFSET) #define WTCON_INT (0x1 << WTCON_INTEN_OFFSET) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_watchdog { unsigned int wtcon; unsigned int wtdat; @@ -52,6 +52,6 @@ struct s5p_watchdog { /* functions */ void wdt_stop(void); void wdt_start(unsigned int timeout); -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5250/cpu.h b/src/cpu/samsung/exynos5250/cpu.h index afd985a..f399a42 100644 --- a/src/cpu/samsung/exynos5250/cpu.h +++ b/src/cpu/samsung/exynos5250/cpu.h @@ -79,7 +79,7 @@ /* Distance between each Trust Zone PC register set */ #define TZPC_BASE_OFFSET 0x10000 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #define SAMSUNG_BASE(device, base) \ static inline unsigned int samsung_get_base_##device(void) \ diff --git a/src/cpu/samsung/exynos5250/spi.h b/src/cpu/samsung/exynos5250/spi.h index 3430ac1..3f36759 100644 --- a/src/cpu/samsung/exynos5250/spi.h +++ b/src/cpu/samsung/exynos5250/spi.h @@ -20,7 +20,7 @@ #ifndef __ASM_ARCH_EXYNOS_COMMON_SPI_H_ #define __ASM_ARCH_EXYNOS_COMMON_SPI_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* SPI peripheral register map; padded to 64KB */ struct exynos_spi { @@ -85,5 +85,5 @@ struct exynos_spi { #define SPI_RX_BYTE_SWAP (1 << 6) #define SPI_RX_HWORD_SWAP (1 << 7) -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/s5p-common/clock.h b/src/cpu/samsung/s5p-common/clock.h index 7b4eb89..c0cd896 100644 --- a/src/cpu/samsung/s5p-common/clock.h +++ b/src/cpu/samsung/s5p-common/clock.h @@ -23,7 +23,7 @@ #ifndef __ASM_ARM_ARCH_CLOCK_H_ #define __ASM_ARM_ARCH_CLOCK_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5pc100_clock { unsigned int apll_lock; unsigned int mpll_lock; diff --git a/src/cpu/samsung/s5p-common/gpio.h b/src/cpu/samsung/s5p-common/gpio.h index 2522808..d098bc8 100644 --- a/src/cpu/samsung/s5p-common/gpio.h +++ b/src/cpu/samsung/s5p-common/gpio.h @@ -23,7 +23,7 @@ #include /* FIXME: for S5PC110_GPIO_BASE */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_gpio_bank { unsigned int con; unsigned int dat; diff --git a/src/cpu/samsung/s5p-common/mmc.h b/src/cpu/samsung/s5p-common/mmc.h index adef4ee..675666c 100644 --- a/src/cpu/samsung/s5p-common/mmc.h +++ b/src/cpu/samsung/s5p-common/mmc.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_MMC_H_ #define __ASM_ARCH_MMC_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_mmc { unsigned int sysad; unsigned short blksize; @@ -69,5 +69,5 @@ struct mmc_host { int s5p_mmc_init(int dev_index, int bus_width); -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/s5p-common/pwm.h b/src/cpu/samsung/s5p-common/pwm.h index 1ac348b..9d9370d 100644 --- a/src/cpu/samsung/s5p-common/pwm.h +++ b/src/cpu/samsung/s5p-common/pwm.h @@ -42,7 +42,7 @@ #define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) #define TCON4_AUTO_RELOAD (1 << 22) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_timer { unsigned int tcfg0; unsigned int tcfg1; @@ -63,7 +63,7 @@ struct s5p_timer { unsigned int tcnto4; unsigned int tintcstat; }; -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ /* FIXME(dhendrix): added missing prototypes... */ int pwm_config(int pwm_id, int duty_ns, int period_ns); diff --git a/src/cpu/samsung/s5p-common/sromc.h b/src/cpu/samsung/s5p-common/sromc.h index 3800a8d..fe73b37 100644 --- a/src/cpu/samsung/s5p-common/sromc.h +++ b/src/cpu/samsung/s5p-common/sromc.h @@ -40,12 +40,12 @@ #define SMC_BC_TACP(x) (x << 4) /* 6clk page mode access cycle */ #define SMC_BC_PMC(x) (x << 0) /* normal(1data)page mode configuration */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_sromc { unsigned int bw; unsigned int bc[6]; }; -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ /* Configure the Band Width and Bank Control Regs for required SROMC Bank */ void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf); diff --git a/src/cpu/samsung/s5p-common/uart.h b/src/cpu/samsung/s5p-common/uart.h index 1c56739..bf396cc 100644 --- a/src/cpu/samsung/s5p-common/uart.h +++ b/src/cpu/samsung/s5p-common/uart.h @@ -23,7 +23,7 @@ #ifndef __ASM_ARCH_UART_H_ #define __ASM_ARCH_UART_H_ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* baudrate rest value */ union br_rest { unsigned short slot; /* udivslot */ @@ -53,6 +53,6 @@ static inline int s5p_uart_divslot(void) return 1; } -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/s5p-common/watchdog.h b/src/cpu/samsung/s5p-common/watchdog.h index 0f80ca5..8c8bf0a 100644 --- a/src/cpu/samsung/s5p-common/watchdog.h +++ b/src/cpu/samsung/s5p-common/watchdog.h @@ -42,7 +42,7 @@ #define WTCON_RESET (0x1 << WTCON_RESET_OFFSET) #define WTCON_INT (0x1 << WTCON_INTEN_OFFSET) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct s5p_watchdog { unsigned int wtcon; unsigned int wtdat; @@ -53,6 +53,6 @@ struct s5p_watchdog { /* functions */ void wdt_stop(void); void wdt_start(unsigned int timeout); -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif From gerrit at coreboot.org Sat Jan 5 01:31:12 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Sat, 5 Jan 2013 01:31:12 +0100 Subject: [coreboot] Patch merged into coreboot/master: 9bcab0c Update 3rdparty mark to latest repository References: Message-ID: the following patch was just integrated into master: commit 9bcab0c72bea6188ebf735ce08ba269ef5f9a272 Author: Stefan Reinauer Date: Fri Jan 4 16:04:34 2013 -0800 Update 3rdparty mark to latest repository Change-Id: I59fca4427345c7e677138b944613a1554d5a8331 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2110 Reviewed-by: Ronald G. Minnich Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Sat Jan 5 01:13:54 2013, giving +1 See http://review.coreboot.org/2110 for details. -gerrit From gerrit at coreboot.org Sat Jan 5 01:31:33 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Sat, 5 Jan 2013 01:31:33 +0100 Subject: [coreboot] Patch set updated for coreboot: 1486cb4 armv7: invoke intermediate build rules References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit 1486cb4ae67c7778f7e75b218f1b85a66c9aa2e6 Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..8176f9a 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Sat Jan 5 01:41:15 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Sat, 5 Jan 2013 01:41:15 +0100 Subject: [coreboot] Patch merged into coreboot/master: 2f25d99 ARMv7: drop __ASSEMBLY__ References: Message-ID: the following patch was just integrated into master: commit 2f25d9963ee6ba57db67a0410fcd932f4be18373 Author: Stefan Reinauer Date: Fri Jan 4 16:29:29 2013 -0800 ARMv7: drop __ASSEMBLY__ We moved to using __ASSEMBLER__ years ago since it is set by as. Change-Id: I60103ba23ebe87be1d0bc63beed0ef5b05eed4f2 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2111 Reviewed-by: Ronald G. Minnich Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Sat Jan 5 01:37:10 2013, giving +1 Reviewed-By: Ronald G. Minnich at Sat Jan 5 01:32:46 2013, giving +2 See http://review.coreboot.org/2111 for details. -gerrit From rhyotte at gmail.com Sat Jan 5 01:10:11 2013 From: rhyotte at gmail.com (gary sheppard) Date: Fri, 4 Jan 2013 16:10:11 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E76DB8.7030507@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> Message-ID: You are correct, "never" is far too long to quantify. I stand corrected. Secure by default because --Big Brother says that it is secure" is tantamount to loss of individuality and personal freedom.-- Perhaps -- Secure by means of openly auditable and verifiable security trace would be better?-- "Big Brother" is not always an answer. On Fri, Jan 4, 2013 at 4:03 PM, Andrew Goodbody wrote: > On 03/01/13 23:23, gary sheppard wrote: > >> Numerous security experts have already said it is anything but secure, >> and it will never be secure. They have only said this quietly, and that >> "voice" has been minimalized, while "PROGRESS" is shouted to the >> heavens. Hey, look at android and how phone makers "lock" it down. Does >> it stay locked? No! Come on people, put your heads out of... ;) >> >> Gary >> > > Security is not an absolute. It is a tradeoff against the time needed to > overcome it. Secure Boot is more secure than no security. coreboot offers > no security. coreboot can never be "the Solution to the Secure Boot Fiasco" > until it can offer better security than Secure Boot. > > Yes there may be breaks for early implementations of Secure Boot but > anyone predicting that it can never be fixed is a very brave person. Never > is a long time. Remember, fixed does not mean perfect. Fixed just means > takes longer to overcome than anyone cares to invest in it. > > Sorry but "this will be broken because everything before it has been > broken" is not a credible critique; that is the inductive fallacy. > > Andrew > -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter at stuge.se Sat Jan 5 02:42:00 2013 From: peter at stuge.se (Peter Stuge) Date: Sat, 5 Jan 2013 02:42:00 +0100 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E773FF.4010401@gmail.com> References: <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> <50E773FF.4010401@gmail.com> Message-ID: <20130105014200.18775.qmail@stuge.se> Andrew Goodbody wrote: >> Andrew, so far, I don't find your arguments very convincing. > > Can you explain to me why Intel would want to control what OS is run on > their chipsets? I expect that they get paid. > Intel are an active contributor to the Linux kernel for their > display drivers. So what? The number of people at Intel working on Linux is pretty small compared to the rest. Don't let their patches trick you. //Peter From david.c.hubbard+coreboot at gmail.com Sat Jan 5 03:11:10 2013 From: david.c.hubbard+coreboot at gmail.com (David Hubbard) Date: Fri, 4 Jan 2013 19:11:10 -0700 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E76F28.9030605@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76F28.9030605@gmail.com> Message-ID: Hi Andrew, On Fri, Jan 4, 2013 at 5:09 PM, Andrew Goodbody wrote: > > Enrol your own key. Sign your own kernel. Seems to scale linearly per user > to me. > > Security is not free. There will always be a cost. > > I am actually quite conflicted because I try to look out for the underdog in every fight. Right now that would be you (no offense intended). Please view my comments as directed at Microsoft and the standard they have pushed onto us. And thanks for debating. "Security is not free" I think the Linux kernel is a glaring hole in that argument. The Linux kernel is *free*, by many definitions. Oh, and it is the *right* way to implement security. Secure Boot is neither libre nor gratis. For $99 you can have a closed DRM solution. All DRM solutions are fundamentally flawed because both lock *and* key must be present on the machine. The only thing DRM has consistently done is inconvenience the average person. "Enrol (sic) your own key. Sign your own kernel." For $99 I could get my kernel signed by Verisign. That does not scale. That was my point, thanks. To attempt to convince all the OEM's to sign their UEFI drivers with my key would be impossible; furthermore, the UEFI spec only has *one* slot for signatures on OEM UEFI drivers. The whole bring-your-own-key argument is a red herring as soon as a third-party driver is involved, because the driver must then be trusted without verifying its signature. You wouldn't accept that kind of security compromise, would you? I know I won't. I'll ditch Secure Boot entirely and use coreboot. Regards, David -------------- next part -------------- An HTML attachment was scrubbed... URL: From gerrit at coreboot.org Sat Jan 5 03:46:00 2013 From: gerrit at coreboot.org (Zheng Bao (zheng.bao@amd.com)) Date: Sat, 5 Jan 2013 03:46:00 +0100 Subject: [coreboot] Patch set updated for coreboot: 112723e AMD: Set the mask of MTRR according to CONFIG_CPU_ADDR_BITS References: Message-ID: Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1661 -gerrit commit 112723e0dc5d5954717487612c353a12fb9d24af Author: Zheng Bao Date: Sat Jan 5 12:17:46 2013 +0800 AMD: Set the mask of MTRR according to CONFIG_CPU_ADDR_BITS The high bits of mtrr mask are MBZ (Must be zero). Writing 1 to these bits will cause exception. So be carefull when spread this change. The supermicro/h8scm needs more work. Currently it is set as it was. We need to check if the F10 and F15 have different value. Change-Id: I2dd8bf07ecee2fe4d1721cec6b21623556e68947 Signed-off-by: Zheng Bao Signed-off-by: zbao --- src/cpu/amd/agesa/family12/Kconfig | 2 +- src/cpu/amd/agesa/family15/Kconfig | 5 +++++ src/cpu/amd/agesa/family15tn/Kconfig | 2 +- src/mainboard/amd/dinar/agesawrapper.c | 2 +- src/mainboard/amd/parmer/agesawrapper.c | 2 +- src/mainboard/amd/thatcher/agesawrapper.c | 2 +- src/mainboard/amd/torpedo/agesawrapper.c | 2 +- src/mainboard/supermicro/h8qgi/agesawrapper.c | 2 +- src/mainboard/supermicro/h8scm/Kconfig | 4 ++++ src/mainboard/supermicro/h8scm/agesawrapper.c | 2 +- src/mainboard/tyan/s8226/agesawrapper.c | 2 +- 11 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/cpu/amd/agesa/family12/Kconfig b/src/cpu/amd/agesa/family12/Kconfig index 87e09d6..6920c9d 100755 --- a/src/cpu/amd/agesa/family12/Kconfig +++ b/src/cpu/amd/agesa/family12/Kconfig @@ -23,7 +23,7 @@ config CPU_AMD_AGESA_FAMILY12 config CPU_ADDR_BITS int - default 36 + default 48 depends on CPU_AMD_AGESA_FAMILY12 config CPU_SOCKET_TYPE diff --git a/src/cpu/amd/agesa/family15/Kconfig b/src/cpu/amd/agesa/family15/Kconfig index c1528f6..f4c1183 100644 --- a/src/cpu/amd/agesa/family15/Kconfig +++ b/src/cpu/amd/agesa/family15/Kconfig @@ -21,6 +21,11 @@ config CPU_AMD_AGESA_FAMILY15 bool select PCI_IO_CFG_EXT +config CPU_ADDR_BITS + int + default 48 + depends on CPU_AMD_AGESA_FAMILY15 + if CPU_AMD_AGESA_FAMILY15 config CPU_AMD_SOCKET_G34 diff --git a/src/cpu/amd/agesa/family15tn/Kconfig b/src/cpu/amd/agesa/family15tn/Kconfig index 8f3a9ff..7459818 100644 --- a/src/cpu/amd/agesa/family15tn/Kconfig +++ b/src/cpu/amd/agesa/family15tn/Kconfig @@ -23,7 +23,7 @@ config CPU_AMD_AGESA_FAMILY15_TN config CPU_ADDR_BITS int - default 36 + default 48 depends on CPU_AMD_AGESA_FAMILY15_TN config CPU_SOCKET_TYPE diff --git a/src/mainboard/amd/dinar/agesawrapper.c b/src/mainboard/amd/dinar/agesawrapper.c index a8ec917..e2b6038 100644 --- a/src/mainboard/amd/dinar/agesawrapper.c +++ b/src/mainboard/amd/dinar/agesawrapper.c @@ -270,7 +270,7 @@ agesawrapper_amdinitmmio ( /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000 - CONFIG_ROM_SIZE) | 5; LibAmdMsrWrite (0x20E, &MsrReg, &StdHeader); - MsrReg = (0x1000000000000ull - CONFIG_ROM_SIZE) | 0x800; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800; LibAmdMsrWrite (0x20F, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; diff --git a/src/mainboard/amd/parmer/agesawrapper.c b/src/mainboard/amd/parmer/agesawrapper.c index c180800..720de43 100644 --- a/src/mainboard/amd/parmer/agesawrapper.c +++ b/src/mainboard/amd/parmer/agesawrapper.c @@ -166,7 +166,7 @@ agesawrapper_amdinitmmio ( /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000ull - CONFIG_ROM_SIZE) | 5ull; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000000ull - CONFIG_ROM_SIZE) | 0x800ull; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800ull; LibAmdMsrWrite (0x20D, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; diff --git a/src/mainboard/amd/thatcher/agesawrapper.c b/src/mainboard/amd/thatcher/agesawrapper.c index 67ac8e9..7a3616b 100644 --- a/src/mainboard/amd/thatcher/agesawrapper.c +++ b/src/mainboard/amd/thatcher/agesawrapper.c @@ -166,7 +166,7 @@ agesawrapper_amdinitmmio ( /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000ull - CONFIG_ROM_SIZE) | 5ull; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000000ull - CONFIG_ROM_SIZE) | 0x800ull; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800ull; LibAmdMsrWrite (0x20D, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; diff --git a/src/mainboard/amd/torpedo/agesawrapper.c b/src/mainboard/amd/torpedo/agesawrapper.c index 2bd1725..2c7b092 100644 --- a/src/mainboard/amd/torpedo/agesawrapper.c +++ b/src/mainboard/amd/torpedo/agesawrapper.c @@ -281,7 +281,7 @@ agesawrapper_amdinitmmio ( /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000ull - CONFIG_ROM_SIZE) | 5ull; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000000ull - CONFIG_ROM_SIZE) | 0x800ull; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800ull; LibAmdMsrWrite (0x20D, &MsrReg, &StdHeader); /* Clear all pending SMI. On S3 clear power button enable so it wll not generate an SMI */ diff --git a/src/mainboard/supermicro/h8qgi/agesawrapper.c b/src/mainboard/supermicro/h8qgi/agesawrapper.c index d354c37..66236ed 100644 --- a/src/mainboard/supermicro/h8qgi/agesawrapper.c +++ b/src/mainboard/supermicro/h8qgi/agesawrapper.c @@ -194,7 +194,7 @@ UINT32 agesawrapper_amdinitmmio(VOID) /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000 - CONFIG_ROM_SIZE) | 5; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000 - CONFIG_ROM_SIZE) | 0x800; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800; LibAmdMsrWrite(0x20D, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; diff --git a/src/mainboard/supermicro/h8scm/Kconfig b/src/mainboard/supermicro/h8scm/Kconfig index e7dae66..b93bfad 100644 --- a/src/mainboard/supermicro/h8scm/Kconfig +++ b/src/mainboard/supermicro/h8scm/Kconfig @@ -59,6 +59,10 @@ config MAX_PHYSICAL_CPUS int default 16 +config CPU_ADDR_BITS + int + default 36 # TODO: Set it conservatively to match both fam10 & 15 + config HW_MEM_HOLE_SIZE_AUTO_INC bool default n diff --git a/src/mainboard/supermicro/h8scm/agesawrapper.c b/src/mainboard/supermicro/h8scm/agesawrapper.c index aeeab11..a841629 100644 --- a/src/mainboard/supermicro/h8scm/agesawrapper.c +++ b/src/mainboard/supermicro/h8scm/agesawrapper.c @@ -194,7 +194,7 @@ UINT32 agesawrapper_amdinitmmio(VOID) /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000 - CONFIG_ROM_SIZE) | 5; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000 - CONFIG_ROM_SIZE) | 0x800; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800; LibAmdMsrWrite(0x20D, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; diff --git a/src/mainboard/tyan/s8226/agesawrapper.c b/src/mainboard/tyan/s8226/agesawrapper.c index 1485354..6f18f5c 100644 --- a/src/mainboard/tyan/s8226/agesawrapper.c +++ b/src/mainboard/tyan/s8226/agesawrapper.c @@ -204,7 +204,7 @@ agesawrapper_amdinitmmio ( /* Set ROM cache onto WP to decrease post time */ MsrReg = (0x0100000000ull - CONFIG_ROM_SIZE) | 5ull; LibAmdMsrWrite (0x20C, &MsrReg, &StdHeader); - MsrReg = (0x1000000000000ull - CONFIG_ROM_SIZE) | 0x800ull; + MsrReg = ((1UL << CONFIG_CPU_ADDR_BITS) - CONFIG_ROM_SIZE) | 0x800ull; LibAmdMsrWrite (0x20D, &MsrReg, &StdHeader); Status = AGESA_SUCCESS; From david.c.hubbard+coreboot at gmail.com Sat Jan 5 00:26:45 2013 From: david.c.hubbard+coreboot at gmail.com (David Hubbard) Date: Fri, 4 Jan 2013 16:26:45 -0700 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E76458.8060401@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76458.8060401@gmail.com> Message-ID: Hi Andrew, On Fri, Jan 4, 2013 at 4:23 PM, Andrew Goodbody wrote: > On 02/01/13 19:28, David Hubbard wrote: > >> Andrew, Ron, what's your take on http://mjg59.dreamwidth.org/**20916.html? >> >> Specifically: >> "This is part of Windows 8's fast boot support - the keyboard may not be >> initialised until after the OS has started." >> > > OK, the feature is deferred initialisation of USB devices until they are > actually needed. > Windows 8 is making use of this but it is introduced as part of the UEFI > spec 2.3.1c. > This is optional to implement it or not, OEM gets to decide. > This is in the UEFI spec and can be used by other OSes than Windows eg > Grub could use it to speed up loading of Linux. > I understand. > > 4. User is thus *forced* to use Win8's "hold down shift and restart" >> feature -- adding another barrier before a user can boot her own OS. >> >> I think the biggest problem here is that the entire BIOS is made >> inaccessible, and only if Windows gives permission can you change that. >> > > Well yes and no. > 1) PS/2 keyboards are not affected, they are still initialised and > available as normal. Many laptop keyboards are implemented as PS/2 devices. > At least AMI BIOS also skips initializing PS/2 keyboards and mice. > 2) There are a number of ways that you can get USB enumerated and > keyboards initialised. > a) If HDD is not primary boot target > b) If primary boot target fails > c) If bootloader invokes EFI_SIMPLE_TEXT_INPUT_EX_**PROTOCOL. > ReadKeyStrokeEx() > > So yes, on a motherboard that implements it, with no PS/2 keyboard, with > the HDD as primary boot target and with Win8 installed then you may have to > use the Win8 menu to restart into the UEFI settings screens. And yes this > can be a small barrier to booting using an alternative method for any > reason, not just installing an alternative OS. But quite frankly I have > seen some bizarre setup screens on legacy BIOS that made choosing to boot > from a USB device an exercise in frustration. So this extra step in the > road to booting an alternate OS is not that big a deal. It can at least be > documented and is not a hard thing to do at all. Even without this there > are some machines that boot so fast it is not easy to press the key to get > to the setup screens at the right time, this may actually give a more > reliable way to get to the setup screens on those machines. > Good point - it could be a more reliable way to be sure the setup screen comes up. > > BTW 1) when you use BIOS above, you actually mean Setup. Setup is an > application launched by the BIOS to view or change system settings. The > BIOS is not accessible nor inaccessible, it is running as soon as the CPU > begins to execute code and will complete its tasks as normal according to > those system settings. > BTW 2) its UEFI firmware, not BIOS. Just as coreboot is not BIOS. > Ok, fine. David -------------- next part -------------- An HTML attachment was scrubbed... URL: From patrick at georgi-clan.de Sat Jan 5 09:26:58 2013 From: patrick at georgi-clan.de (Patrick Georgi) Date: Sat, 05 Jan 2013 09:26:58 +0100 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E76DB8.7030507@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> Message-ID: Am 2013-01-05 01:03, schrieb Andrew Goodbody: > coreboot can never be "the Solution to the Secure > Boot Fiasco" until it can offer better security than Secure Boot. We do. Same level of verifiable boot (by doing signature checks on loaded code) without the UEFI complexity. Microsoft made Phoenix implement ASLR and NX bit support to lock down the firmware some more (see UEFI plugfest slides of 2011/2012). That's complexity just to manage existing complexity. And now AMI dreams of an UEFI OpenGL library (also plugfest slides). coreboot has neither: No ASLR, but we don't run any custom code before jumping into the signed kernel, which can't do callbacks. No need for NX bit support for the same reason. No loadable modules that require signature checks. No resident API for operating systems (and no attack surface that results from this). And no plans for an OpenGL library - since with coreboot, firmware is long gone when OpenGL becomes interesting. (though someone could arguably push Linux + initrd with libGL.so into flash as a payload) From an execution stand point, our secure boot approaches are quite similar: signed binaries with (RSA) signature checks. The issues over time were similar (my prototype for such functionality in 2008 had TOCTOU issues, they solved similar problems in 2011). Just the signature formats vary. But we aim for simplicity, which is a quality of its own - especially when it comes to security. In fact, even the "Freedom" issues are similar: Google voluntarily did the right thing and added a user override button (hardware) to their chrome devices. Without that, coreboot in those systems wouldn't help a bit, since they'd be just as locked down as a UEFI secure boot device without custom key enrollment. The issue with UEFI Secure Boot is the motivation of the guardian of standard and implementation. It's not Intel, it's Microsoft: They worked with (and/or paid) Insyde to do the secure boot implementation. They worked with (and/or paid) Phoenix for the ASLR/NX lock down. And they add a bunch of requirements for hardware implementors that exceed the UEFI spec by way of their Windows Logo initiative. It definitely matters right now for PC platforms where the Win8 Logo requirements only changed to the current state (so that they _require_ a key enrollment option for the user, and a way to disable secure boot) after public pressure. PC is a market they control, so vendors can't ignore the Win Logo stuff. Patrick From ajg4tadpole at gmail.com Sat Jan 5 14:44:09 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Sat, 05 Jan 2013 13:44:09 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76F28.9030605@gmail.com> Message-ID: <50E82E29.1060903@gmail.com> On 05/01/13 02:11, David Hubbard wrote: > Hi Andrew, > > On Fri, Jan 4, 2013 at 5:09 PM, Andrew Goodbody > wrote: > > > Enrol your own key. Sign your own kernel. Seems to scale linearly > per user to me. > > Security is not free. There will always be a cost. > > > I am actually quite conflicted because I try to look out for the > underdog in every fight. Right now that would be you (no offense > intended). Please view my comments as directed at Microsoft and the > standard they have pushed onto us. And thanks for debating. No offense taken. I have never been one for following the crowd just because. Debate is good. > "Security is not free" > > I think the Linux kernel is a glaring hole in that argument. The Linux > kernel is *free*, by many definitions. Oh, and it is the *right* way to > implement security. There is always a cost to security. The cost for Linux is that certain operations need privileged access so you have to do something special (su, sudo etc) in order to complete those operations. That is the sort of cost I am talking about when I say not free. There is also the added complexity in the code requiring careful maintenance and simply more time to implement. So yes security is not free. > Secure Boot is neither libre nor gratis. For $99 you can have a closed > DRM solution. All DRM solutions are fundamentally flawed because both > lock *and* key must be present on the machine. The only thing DRM has > consistently done is inconvenience the average person. You only need to pay the $99 if you do not want to enrol your own key. The point of PKI is that you can see the public key without being able to guess the private key. It is bugs in the implementation or leaks of the private key that have compromised current PKI systems, not fundamental flaws in the cryptography. > "Enrol (sic) your own key. Sign your own kernel." 'Enrol' is correct English. For some reason American English adds a superfluous 'l' :-) > For $99 I could get my kernel signed by Verisign. That does not scale. > That was my point, thanks. And my point was that you do not have to play that game. You can use Secure Boot without paying a penny to anybody. If you do not want to enrol your own key then you can use shim instead. You can go on compiling your own kernel and use Secure Boot without having to get it signed by Verisign every time. > To attempt to convince all the OEM's to sign their UEFI drivers with my > key would be impossible; furthermore, the UEFI spec only has *one* slot > for signatures on OEM UEFI drivers. Not true. Current tools only implement a single signing slot but there are tools being developed to allow multiple signatures. This will then need to be supported in the Secure Boot implementations so may not work on initial implementations. http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=SecurityPkg > The whole bring-your-own-key argument is a red herring as soon as a > third-party driver is involved, because the driver must then be trusted > without verifying its signature. You wouldn't accept that kind of > security compromise, would you? The whole 3rd party driver thing complicates matters for sure. First of all do you even trust that driver? If you do then you can sign it and overwrite the signature it was shipped with. Also I believe that you can enrol a hash of a driver as an alternative means of verification to signature based verification although that may depend on the policy of that platform. > I know I won't. I'll ditch Secure Boot entirely and use coreboot. > > Regards, > David Thanks for listening, Andrew From ajg4tadpole at gmail.com Sat Jan 5 15:03:30 2013 From: ajg4tadpole at gmail.com (Andrew Goodbody) Date: Sat, 05 Jan 2013 14:03:30 +0000 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> Message-ID: <50E832B2.3040506@gmail.com> On 05/01/13 08:26, Patrick Georgi wrote: > Am 2013-01-05 01:03, schrieb Andrew Goodbody: >> coreboot can never be "the Solution to the Secure >> Boot Fiasco" until it can offer better security than Secure Boot. > We do. Same level of verifiable boot (by doing signature checks on > loaded code) without the UEFI complexity. Ahh, sorry I missed that detail didn't I? That's really good to know. > In fact, even the "Freedom" issues are similar: Google voluntarily did > the right thing and added a user override button (hardware) to their > chrome devices. Without that, coreboot in those systems wouldn't help a > bit, since they'd be just as locked down as a UEFI secure boot device > without custom key enrollment. And here is the crux of the issue. Distribution and management of keys is a major problem be it coreboot or Secure Boot. > The issue with UEFI Secure Boot is the motivation of the guardian of > standard and implementation. It's not Intel, it's Microsoft: They worked > with (and/or paid) Insyde to do the secure boot implementation. They > worked with (and/or paid) Phoenix for the ASLR/NX lock down. > And they add a bunch of requirements for hardware implementors that > exceed the UEFI spec by way of their Windows Logo initiative. > > It definitely matters right now for PC platforms where the Win8 Logo > requirements only changed to the current state (so that they _require_ a > key enrollment option for the user, and a way to disable secure boot) > after public pressure. > PC is a market they control, so vendors can't ignore the Win Logo stuff. > > > Patrick > Agree 100%. I do not understand why people are lumping Intel in with Microsoft on this one. I actually find the fact that Microsoft bowed to the public outcry and added the requirement for key enrolment to be an encouraging thing. If there is a single message that is not fuelled by paranoia and FUD then changes can actually be made. Just FYI MS have been controlling PC hardware since they released the PC98 specification so this is not a new move on their part but it is an escalation. Andrew From patrick at georgi-clan.de Sat Jan 5 15:52:18 2013 From: patrick at georgi-clan.de (Patrick Georgi) Date: Sat, 05 Jan 2013 15:52:18 +0100 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E832B2.3040506@gmail.com> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> <50E832B2.3040506@gmail.com> Message-ID: <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> Am 2013-01-05 15:03, schrieb Andrew Goodbody: > Ahh, sorry I missed that detail didn't I? That's really good to know. It's not as obvious, since that's a payload feature, not coreboot itself. > And here is the crux of the issue. Distribution and management of > keys is a major problem be it coreboot or Secure Boot. The major issue is the (lack of) willingness of vendors to hand over control over devices to their customers (who _bought_ the devices) like they used to. Key management is a minor technical detail - chrome devices have the proper implementation (hardware switch to indicate user override), Shim provides the best possible solution within the UEFI secureboot framework, as long as key enrollment is at all possible. > Agree 100%. I do not understand why people are lumping Intel in with > Microsoft on this one. Probably because UEFI is considered Intel's brainchild, even though it's a huge committee these days. > I actually find the fact that Microsoft bowed to the public outcry > and added the requirement for key enrolment to be an encouraging > thing. If there is a single message that is not fuelled by paranoia > and FUD then changes can actually be made. The other reason for allowing secure boot to be disabled is Windows 7. And if they allow it to be disabled, it doesn't hurt to allow key enrollment. We don't know _what_ pressure made them change their mind. It's possible that PC vendors would have refused Windows 8 Logo for 2013/2014 devices to keep Windows 7 (or even XP) compatibility around for their business customers. If you want to discern Microsoft's actual intentions, it's best to look at the platforms that aren't bogged down by compatibility requirements: Win64 introduced mandantory driver signatures (since old 32bit drivers didn't run anyway), Windows on ARM introduced mandantory Secure Boot (with no custom key enrollment in sight). > Just FYI MS have been controlling PC hardware since they released the > PC98 specification so this is not a new move on their part but it is > an escalation. Sure, but it shows that pointing to the UEFI spec (and its siblings, PI and so on) isn't enough. What actually happens on devices out there is defined by Windows Logo requirements (and they're generally good ideas even, and forced BIOS vendors to fix their code for a while now. For example, Windows7+ explicitely tests that BIOS doesn't mess up the <1MB RAM area on suspend/wakeup, because BIOS commonly did so). Summary: - Verified boot processes work with coreboot and UEFI alike (within their respective world views) - UEFI Secure Boot is driven by Microsoft, not (as much) by Intel - Microsoft's motivation is partly to provide a secure environment (after their embarassing history of Windows (in)security) - Microsoft won't shed a tear if they get away with killing competition via "security" initiatives - UEFI Secure Boot key management is done by the old Microsoft/Verisign team. Probably out of convenience (they have some history of managing driver signatures), but politically unwise any maybe malign. So while Secure Boot is a nice idea if kept user-overrideable, it's in the wrong hands with no existing process to resolve that (UEFI Forum is the only semi public instance in that ecosystemen, it's paid-membership based, and they're also not responsible for the implementation of key management we have). The remaining theoretical option within the UEFI ecosystem is to pressure the UEFI Forum members to define secure boot overrides mandantory on all device classes in all future versions of UEFI. That way control over this dangerous feature is taken away from Microsoft and brought into the forum, which has a broader interest base than just Microsoft's. I doubt that could happen, but I'll be truly happy to be proven wrong here. The other option is to keep coreboot viable. Since I'm more technically inclined, that what I'll aim for. Patrick From gerrit at coreboot.org Sun Jan 6 08:57:37 2013 From: gerrit at coreboot.org (Zheng Bao (zheng.bao@amd.com)) Date: Sun, 6 Jan 2013 08:57:37 +0100 Subject: [coreboot] New patch to review for coreboot: 51e741c cbfstool: "index" is not supported in mingw. References: Message-ID: Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2112 -gerrit commit 51e741c5ae616a16f45b53c580bea8f9168cacdb Author: zbao Date: Sun Jan 6 15:59:06 2013 +0800 cbfstool: "index" is not supported in mingw. Use strchr instead. Change-Id: I3899b9ca9196dbbf2d147a38dacd7e742a3873fe Signed-off-by: Zheng Bao Signed-off-by: zbao --- util/cbfstool/cbfstool.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 6b52062..d5a751f 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -28,6 +28,10 @@ #include "common.h" #include "cbfs.h" +#ifdef __MINGW32__ +#define index strchr +#endif + struct command { const char *name; const char *optstring; From rhyotte at gmail.com Sat Jan 5 20:58:01 2013 From: rhyotte at gmail.com (gary sheppard) Date: Sat, 5 Jan 2013 11:58:01 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> <50E832B2.3040506@gmail.com> <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> Message-ID: And for those of us who simply do not trust Big Brother MS to forgo giving us an Atomic Wedgie... My next system upgrade will have Coreboot if that is even remotely possible. I prefer OPEN to Closed pretty much every time. Gary On Sat, Jan 5, 2013 at 6:52 AM, Patrick Georgi wrote: > Am 2013-01-05 15:03, schrieb Andrew Goodbody: > > Ahh, sorry I missed that detail didn't I? That's really good to know. >> > It's not as obvious, since that's a payload feature, not coreboot itself. > > > And here is the crux of the issue. Distribution and management of >> keys is a major problem be it coreboot or Secure Boot. >> > The major issue is the (lack of) willingness of vendors to hand over > control over devices to their customers (who _bought_ the devices) like > they used to. > > Key management is a minor technical detail - chrome devices have the > proper implementation (hardware switch to indicate user override), Shim > provides the best possible solution within the UEFI secureboot framework, > as long as key enrollment is at all possible. > > > Agree 100%. I do not understand why people are lumping Intel in with >> Microsoft on this one. >> > Probably because UEFI is considered Intel's brainchild, even though it's a > huge committee these days. > > > I actually find the fact that Microsoft bowed to the public outcry >> and added the requirement for key enrolment to be an encouraging >> thing. If there is a single message that is not fuelled by paranoia >> and FUD then changes can actually be made. >> > The other reason for allowing secure boot to be disabled is Windows 7. And > if they allow it to be disabled, it doesn't hurt to allow key enrollment. > > We don't know _what_ pressure made them change their mind. It's possible > that PC vendors would have refused Windows 8 Logo for 2013/2014 devices to > keep Windows 7 (or even XP) compatibility around for their business > customers. > > If you want to discern Microsoft's actual intentions, it's best to look at > the platforms that aren't bogged down by compatibility requirements: Win64 > introduced mandantory driver signatures (since old 32bit drivers didn't run > anyway), Windows on ARM introduced mandantory Secure Boot (with no custom > key enrollment in sight). > > > Just FYI MS have been controlling PC hardware since they released the >> PC98 specification so this is not a new move on their part but it is >> an escalation. >> > Sure, but it shows that pointing to the UEFI spec (and its siblings, PI > and so on) isn't enough. What actually happens on devices out there is > defined by Windows Logo requirements (and they're generally good ideas > even, and forced BIOS vendors to fix their code for a while now. For > example, Windows7+ explicitely tests that BIOS doesn't mess up the <1MB RAM > area on suspend/wakeup, because BIOS commonly did so). > > Summary: > - Verified boot processes work with coreboot and UEFI alike (within their > respective world views) > - UEFI Secure Boot is driven by Microsoft, not (as much) by Intel > - Microsoft's motivation is partly to provide a secure environment (after > their embarassing history of Windows (in)security) > - Microsoft won't shed a tear if they get away with killing competition > via "security" initiatives > - UEFI Secure Boot key management is done by the old Microsoft/Verisign > team. Probably out of convenience (they have some history of managing > driver signatures), but politically unwise any maybe malign. > > So while Secure Boot is a nice idea if kept user-overrideable, it's in the > wrong hands with no existing process to resolve that (UEFI Forum is the > only semi public instance in that ecosystemen, it's paid-membership based, > and they're also not responsible for the implementation of key management > we have). > > The remaining theoretical option within the UEFI ecosystem is to pressure > the UEFI Forum members to define secure boot overrides mandantory on all > device classes in all future versions of UEFI. That way control over this > dangerous feature is taken away from Microsoft and brought into the forum, > which has a broader interest base than just Microsoft's. > I doubt that could happen, but I'll be truly happy to be proven wrong here. > > The other option is to keep coreboot viable. Since I'm more technically > inclined, that what I'll aim for. > > > Patrick > > > -- > coreboot mailing list: coreboot at coreboot.org > http://www.coreboot.org/**mailman/listinfo/coreboot > -------------- next part -------------- An HTML attachment was scrubbed... URL: From r.marek at assembler.cz Sun Jan 6 10:21:12 2013 From: r.marek at assembler.cz (Rudolf Marek) Date: Sun, 06 Jan 2013 10:21:12 +0100 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> <50E832B2.3040506@gmail.com> <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> Message-ID: <50E94208.7020107@assembler.cz> > And for those of us who simply do not trust Big Brother MS to forgo giving us an > Atomic Wedgie... My next system upgrade will have Coreboot if that is even > remotely possible. I prefer OPEN to Closed pretty much every time. So far so good. What kind of system do you prefer? Is there any particular system you want to see supported? I work on Asus F2A85-M or check the wiki pages for other possibilites. Thanks Rudolf > > Gary > > > On Sat, Jan 5, 2013 at 6:52 AM, Patrick Georgi > wrote: > > Am 2013-01-05 15:03, schrieb Andrew Goodbody: > > Ahh, sorry I missed that detail didn't I? That's really good to know. > > It's not as obvious, since that's a payload feature, not coreboot itself. > > > And here is the crux of the issue. Distribution and management of > keys is a major problem be it coreboot or Secure Boot. > > The major issue is the (lack of) willingness of vendors to hand over control > over devices to their customers (who _bought_ the devices) like they used to. > > Key management is a minor technical detail - chrome devices have the proper > implementation (hardware switch to indicate user override), Shim provides > the best possible solution within the UEFI secureboot framework, as long as > key enrollment is at all possible. > > > Agree 100%. I do not understand why people are lumping Intel in with > Microsoft on this one. > > Probably because UEFI is considered Intel's brainchild, even though it's a > huge committee these days. > > > I actually find the fact that Microsoft bowed to the public outcry > and added the requirement for key enrolment to be an encouraging > thing. If there is a single message that is not fuelled by paranoia > and FUD then changes can actually be made. > > The other reason for allowing secure boot to be disabled is Windows 7. And > if they allow it to be disabled, it doesn't hurt to allow key enrollment. > > We don't know _what_ pressure made them change their mind. It's possible > that PC vendors would have refused Windows 8 Logo for 2013/2014 devices to > keep Windows 7 (or even XP) compatibility around for their business customers. > > If you want to discern Microsoft's actual intentions, it's best to look at > the platforms that aren't bogged down by compatibility requirements: Win64 > introduced mandantory driver signatures (since old 32bit drivers didn't run > anyway), Windows on ARM introduced mandantory Secure Boot (with no custom > key enrollment in sight). > > > Just FYI MS have been controlling PC hardware since they released the > PC98 specification so this is not a new move on their part but it is > an escalation. > > Sure, but it shows that pointing to the UEFI spec (and its siblings, PI and > so on) isn't enough. What actually happens on devices out there is defined > by Windows Logo requirements (and they're generally good ideas even, and > forced BIOS vendors to fix their code for a while now. For example, > Windows7+ explicitely tests that BIOS doesn't mess up the <1MB RAM area on > suspend/wakeup, because BIOS commonly did so). > > Summary: > - Verified boot processes work with coreboot and UEFI alike (within their > respective world views) > - UEFI Secure Boot is driven by Microsoft, not (as much) by Intel > - Microsoft's motivation is partly to provide a secure environment (after > their embarassing history of Windows (in)security) > - Microsoft won't shed a tear if they get away with killing competition via > "security" initiatives > - UEFI Secure Boot key management is done by the old Microsoft/Verisign > team. Probably out of convenience (they have some history of managing driver > signatures), but politically unwise any maybe malign. > > So while Secure Boot is a nice idea if kept user-overrideable, it's in the > wrong hands with no existing process to resolve that (UEFI Forum is the only > semi public instance in that ecosystemen, it's paid-membership based, and > they're also not responsible for the implementation of key management we have). > > The remaining theoretical option within the UEFI ecosystem is to pressure > the UEFI Forum members to define secure boot overrides mandantory on all > device classes in all future versions of UEFI. That way control over this > dangerous feature is taken away from Microsoft and brought into the forum, > which has a broader interest base than just Microsoft's. > I doubt that could happen, but I'll be truly happy to be proven wrong here. > > The other option is to keep coreboot viable. Since I'm more technically > inclined, that what I'll aim for. > > > Patrick > > > -- > coreboot mailing list: coreboot at coreboot.org > http://www.coreboot.org/__mailman/listinfo/coreboot > > > > > From rhyotte at gmail.com Sun Jan 6 11:10:42 2013 From: rhyotte at gmail.com (gary sheppard) Date: Sun, 6 Jan 2013 02:10:42 -0800 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: <50E94208.7020107@assembler.cz> References: <50E1E294.9060802@gmail.com> <50E47543.8050102@gmail.com> <50E76DB8.7030507@gmail.com> <50E832B2.3040506@gmail.com> <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> <50E94208.7020107@assembler.cz> Message-ID: Rudolf, I have been watching the Intel Haswell cpu's. The Intel GPU initiative in linux seems pretty strong lately. Have a good one, Gary On Sun, Jan 6, 2013 at 1:21 AM, Rudolf Marek wrote: > And for those of us who simply do not trust Big Brother MS to forgo giving >> us an >> Atomic Wedgie... My next system upgrade will have Coreboot if that is even >> remotely possible. I prefer OPEN to Closed pretty much every time. >> > > So far so good. What kind of system do you prefer? Is there any particular > system you want to see supported? I work on Asus F2A85-M or check the wiki > pages for other possibilites. > > Thanks > Rudolf > > > >> Gary >> >> >> On Sat, Jan 5, 2013 at 6:52 AM, Patrick Georgi > > wrote: >> >> Am 2013-01-05 15:03, schrieb Andrew Goodbody: >> >> Ahh, sorry I missed that detail didn't I? That's really good to >> know. >> >> It's not as obvious, since that's a payload feature, not coreboot >> itself. >> >> >> And here is the crux of the issue. Distribution and management of >> keys is a major problem be it coreboot or Secure Boot. >> >> The major issue is the (lack of) willingness of vendors to hand over >> control >> over devices to their customers (who _bought_ the devices) like they >> used to. >> >> Key management is a minor technical detail - chrome devices have the >> proper >> implementation (hardware switch to indicate user override), Shim >> provides >> the best possible solution within the UEFI secureboot framework, as >> long as >> key enrollment is at all possible. >> >> >> Agree 100%. I do not understand why people are lumping Intel in >> with >> Microsoft on this one. >> >> Probably because UEFI is considered Intel's brainchild, even though >> it's a >> huge committee these days. >> >> >> I actually find the fact that Microsoft bowed to the public outcry >> and added the requirement for key enrolment to be an encouraging >> thing. If there is a single message that is not fuelled by >> paranoia >> and FUD then changes can actually be made. >> >> The other reason for allowing secure boot to be disabled is Windows >> 7. And >> if they allow it to be disabled, it doesn't hurt to allow key >> enrollment. >> >> We don't know _what_ pressure made them change their mind. It's >> possible >> that PC vendors would have refused Windows 8 Logo for 2013/2014 >> devices to >> keep Windows 7 (or even XP) compatibility around for their business >> customers. >> >> If you want to discern Microsoft's actual intentions, it's best to >> look at >> the platforms that aren't bogged down by compatibility requirements: >> Win64 >> introduced mandantory driver signatures (since old 32bit drivers >> didn't run >> anyway), Windows on ARM introduced mandantory Secure Boot (with no >> custom >> key enrollment in sight). >> >> >> Just FYI MS have been controlling PC hardware since they released >> the >> PC98 specification so this is not a new move on their part but it >> is >> an escalation. >> >> Sure, but it shows that pointing to the UEFI spec (and its siblings, >> PI and >> so on) isn't enough. What actually happens on devices out there is >> defined >> by Windows Logo requirements (and they're generally good ideas even, >> and >> forced BIOS vendors to fix their code for a while now. For example, >> Windows7+ explicitely tests that BIOS doesn't mess up the <1MB RAM >> area on >> suspend/wakeup, because BIOS commonly did so). >> >> Summary: >> - Verified boot processes work with coreboot and UEFI alike (within >> their >> respective world views) >> - UEFI Secure Boot is driven by Microsoft, not (as much) by Intel >> - Microsoft's motivation is partly to provide a secure environment >> (after >> their embarassing history of Windows (in)security) >> - Microsoft won't shed a tear if they get away with killing >> competition via >> "security" initiatives >> - UEFI Secure Boot key management is done by the old >> Microsoft/Verisign >> team. Probably out of convenience (they have some history of managing >> driver >> signatures), but politically unwise any maybe malign. >> >> So while Secure Boot is a nice idea if kept user-overrideable, it's >> in the >> wrong hands with no existing process to resolve that (UEFI Forum is >> the only >> semi public instance in that ecosystemen, it's paid-membership based, >> and >> they're also not responsible for the implementation of key management >> we have). >> >> The remaining theoretical option within the UEFI ecosystem is to >> pressure >> the UEFI Forum members to define secure boot overrides mandantory on >> all >> device classes in all future versions of UEFI. That way control over >> this >> dangerous feature is taken away from Microsoft and brought into the >> forum, >> which has a broader interest base than just Microsoft's. >> I doubt that could happen, but I'll be truly happy to be proven wrong >> here. >> >> The other option is to keep coreboot viable. Since I'm more >> technically >> inclined, that what I'll aim for. >> >> >> Patrick >> >> >> -- >> coreboot mailing list: coreboot at coreboot.org > coreboot at coreboot.org> >> http://www.coreboot.org/__**mailman/listinfo/coreboot >> >> > >> >> >> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter at stuge.se Mon Jan 7 13:21:14 2013 From: peter at stuge.se (Peter Stuge) Date: Mon, 7 Jan 2013 13:21:14 +0100 Subject: [coreboot] Feedback On Coreboot: the Solution to the Secure Boot Fiasco In-Reply-To: References: <50E76DB8.7030507@gmail.com> <50E832B2.3040506@gmail.com> <6949126fe8b5d276d8ee742a5dfe2963@mail.georgi-clan.de> <50E94208.7020107@assembler.cz> Message-ID: <20130107122114.10653.qmail@stuge.se> gary sheppard wrote: > I have been watching the Intel Haswell cpu's. The Intel GPU > initiative in linux seems pretty strong lately. You will unfortunately have to change your mindset if you want to make coreboot a priority. :\ //Peter From peter at stuge.se Mon Jan 7 15:38:58 2013 From: peter at stuge.se (Peter Stuge) Date: Mon, 7 Jan 2013 15:38:58 +0100 Subject: [coreboot] [SPAM] Re: Feedback On Coreboot: the Solution to the SecureBoot Fiasco In-Reply-To: <59005.1357568941@tinet.org> References: <59005.1357568941@tinet.org> Message-ID: <20130107143859.29591.qmail@stuge.se> Xavi Drudis Ferran wrote: > My impression is that we're headed to a world were there'll be open > hardware plataforms, running free software and accessing more or > less free content, and mainstream closed hardware running nonfre > software and accessing DRMized content. With little or no bidges > between these worlds. We are already living in this future. Take a look at smartphones. //Peter From xdrudis at tinet.cat Mon Jan 7 15:29:01 2013 From: xdrudis at tinet.cat (Xavi Drudis Ferran) Date: Mon, 07 Jan 2013 15:29:01 +0100 Subject: [coreboot] [SPAM] Re: Feedback On Coreboot: the Solution to the SecureBoot Fiasco Message-ID: <59005.1357568941@tinet.org> I've read the whole thread and I agree with Ron and Gary. Devices that won't boot the software that the user chooses are traps and should never be bought. Even devices that let the user control the keys they trust are regrettable. The only solution would be a massive rejection of the whole scheme. On one hand I doubt the security of rejecting unsigned code is worth turning a gerneral purpose computer in a machine that will only run a finite set of software or will run untrusted software with restrictions. It's like havign less of the general machine you meant to buy. On the other even if we keep our freedom to run what we want we have already lost the freedom of running what we want without others being able to know what we run (in fact being able to tell we don't run what they trust). For now secure boot only restricts what we boot (and the booted OS restricts the rest of what we run). But in the end the purpuse is to stablish a DRM scheme so that if a server can't prove that we're running software trusted by them (not us) then we won't be able to access content or even we'll be refused connection to the internet or whatever has to do with equipment controlled by someone else. So yes, the only solution is, as Ron suggested to plainly reject the scheme, to avoid buying, running, working around these sort of restrictions. And still this is only useful if the majority of people does it. Then the providers of internet access, connectivity or whatever we want of others won't find interesting to restrict their business to the few secure booters. I'm not so optimistic about how feasible this is now and how feasible it gets each day. Intel CPUs are sold in equipment with intel GPUs. Intel GPUS have free software drivers, but Intel did not provide code or documentation to boot their CPUs (does it now ? at least Google paid for some free code so it's better than it was, right?). Modern Intel CPUs need to run signed, propietary code before they can even access RAM. AMD contributes code to coreboot and documents their processors well. But then their GPUs (wih computing power and acces to main memory, etc.) run some form of propietary code (even with the free software drivers). And I heard their lates GPUs don't even have good support in this kind of free drivers with propietary AtomBIOS. And the tools to implement secure boot are there too, so once everybody runs secure booted platforms people may be able to tell we're not. Likiwise new ARM processors are getting TrustZone and similar technology (and often require propietary drivers for GPUs). I haven't heard so much for MIPS, but I haven't heard of similarly powerful MIPS processors either. So our choices are not very nice, even if some choices are nicer than others. My impression is that we're headed to a world were there'll be open hardware plataforms, running free software and accessing more or less free content, and mainstream closed hardware running nonfre software and accessing DRMized content. With little or no bidges between these worlds. And hardware does not have the same economics of software, so being a niche market can be harder than when free software and propietary software could run on the same hardware. It's a pity, but people aren't protesting enough. From ward at gnu.org Mon Jan 7 21:35:31 2013 From: ward at gnu.org (Ward Vandewege) Date: Mon, 7 Jan 2013 15:35:31 -0500 Subject: [coreboot] [SPAM] Re: Feedback On Coreboot: the Solution to the SecureBoot Fiasco In-Reply-To: <59005.1357568941@tinet.org> References: <59005.1357568941@tinet.org> Message-ID: <20130107203531.GA23416@countzero.vandewege.net> On Mon, Jan 07, 2013 at 03:29:01PM +0100, Xavi Drudis Ferran wrote: > For now secure boot only restricts what we boot (and the booted OS restricts the rest > of what we run). But in the end the purpuse is to stablish a DRM scheme so that > if a server can't prove that we're running software trusted by them (not us) then we won't > be able to access content or even we'll be refused connection to the internet or whatever > has to do with equipment controlled by someone else. This. It's called 'remote attestation' (https://en.wikipedia.org/wiki/Trusted_Computing#Remote_attestation). An obvious (first?) application will be your bank, which will refuse you access to their online banking system unless you run a 'trusted' software stack. And you can be sure that their idea of a 'trusted' stack will be proprietary software, only. Because we all know that Windows is the most secure operating system out there (/sarcasm). Thanks, Ward. From gerrit at coreboot.org Mon Jan 7 22:24:07 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Mon, 7 Jan 2013 22:24:07 +0100 Subject: [coreboot] New patch to review for coreboot: 6236709 qemu-x86: Implement more features References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2113 -gerrit commit 62367091b42a97eb70cef062d5bbbf85ede6abc0 Author: Stefan Reinauer Date: Mon Jan 7 13:21:22 2013 -0800 qemu-x86: Implement more features This patch switches the Qemu target to use (pseudo) Cache As RAM and enables some ACPI code. This allows to use the CBMEM console and timestamp code with coreboot in Qemu. Right now, the ACPI code is commented out because leaving it in breaks IDE. Change-Id: Ie20f3ecc194004f354ae3437b9cf9175382cadf8 Signed-off-by: Stefan Reinauer --- src/mainboard/emulation/qemu-x86/Kconfig | 13 +- src/mainboard/emulation/qemu-x86/Makefile.inc | 1 + src/mainboard/emulation/qemu-x86/acpi_tables.c | 193 +++++ src/mainboard/emulation/qemu-x86/cache_as_ram.inc | 100 +++ src/mainboard/emulation/qemu-x86/devicetree.cb | 2 +- src/mainboard/emulation/qemu-x86/dsdt.asl | 958 ++++++++++++++++++++++ src/mainboard/emulation/qemu-x86/mainboard.c | 24 +- src/mainboard/emulation/qemu-x86/memory.c | 47 ++ src/mainboard/emulation/qemu-x86/northbridge.c | 16 +- src/mainboard/emulation/qemu-x86/romstage.c | 46 +- 10 files changed, 1380 insertions(+), 20 deletions(-) diff --git a/src/mainboard/emulation/qemu-x86/Kconfig b/src/mainboard/emulation/qemu-x86/Kconfig index db1a027..c171309 100644 --- a/src/mainboard/emulation/qemu-x86/Kconfig +++ b/src/mainboard/emulation/qemu-x86/Kconfig @@ -4,9 +4,11 @@ config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select ARCH_X86 select SOUTHBRIDGE_INTEL_I82371EB - select ROMCC + select CACHE_AS_RAM select HAVE_OPTION_TABLE select HAVE_PIRQ_TABLE + select HAVE_ACPI_TABLES + select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_256 config MAINBOARD_DIR @@ -21,4 +23,13 @@ config IRQ_SLOT_COUNT int default 6 +config DCACHE_RAM_BASE + hex + default 0xd0000 + +config DCACHE_RAM_SIZE + hex + default 0x10000 + + endif # BOARD_EMULATION_QEMU_X86 diff --git a/src/mainboard/emulation/qemu-x86/Makefile.inc b/src/mainboard/emulation/qemu-x86/Makefile.inc index 5ba0d14..93f9cc2 100644 --- a/src/mainboard/emulation/qemu-x86/Makefile.inc +++ b/src/mainboard/emulation/qemu-x86/Makefile.inc @@ -1,3 +1,4 @@ ROMCCFLAGS := -mcpu=i386 -O +cpu_incs += $(src)/mainboard/emulation/qemu-x86/cache_as_ram.inc ramstage-y += northbridge.c diff --git a/src/mainboard/emulation/qemu-x86/acpi_tables.c b/src/mainboard/emulation/qemu-x86/acpi_tables.c new file mode 100644 index 0000000..de8d7f1 --- /dev/null +++ b/src/mainboard/emulation/qemu-x86/acpi_tables.c @@ -0,0 +1,193 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ +#ifdef ACPI + unsigned long current; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +#else + return start; +#endif +} diff --git a/src/mainboard/emulation/qemu-x86/cache_as_ram.inc b/src/mainboard/emulation/qemu-x86/cache_as_ram.inc new file mode 100644 index 0000000..5eca79b --- /dev/null +++ b/src/mainboard/emulation/qemu-x86/cache_as_ram.inc @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2007-2008 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#define CACHE_AS_RAM_SIZE 0x10000 +#define CACHE_AS_RAM_BASE 0xd0000 + +#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1) + + /* Save the BIST result. */ + movl %eax, %ebp + +cache_as_ram: + post_code(0x20) + /* Clear the cache memory region. This will also fill up the cache */ + movl $CACHE_AS_RAM_BASE, %esi + movl %esi, %edi + movl $(CACHE_AS_RAM_SIZE / 4), %ecx + // movl $0x23322332, %eax + xorl %eax, %eax + rep stosl + + post_code(0x21) + /* Set up the stack pointer. */ + movl $(CACHE_AS_RAM_SIZE + CACHE_AS_RAM_BASE - 4), %eax + movl %eax, %esp + + /* Restore the BIST result. */ + movl %ebp, %eax + movl %esp, %ebp + pushl %eax + +before_romstage: + post_code(0x29) + /* Call romstage.c main function. */ + call main + + post_code(0x30) + +#if CONFIG_HAVE_ACPI_RESUME + movl CBMEM_BOOT_MODE, %eax + cmpl $0x2, %eax // Resume? + jne __acpi_resume_backup_done + + /* copy 1MB - 64K to high tables ram_base to prevent memory corruption + * through stage 2. We could keep stuff like stack and heap in high + * tables memory completely, but that's a wonderful clean up task for + * another day. + */ + cld + movl $CONFIG_RAMBASE, %esi + movl CBMEM_RESUME_BACKUP, %edi + movl $HIGH_MEMORY_SAVE / 4, %ecx + rep movsl + +__acpi_resume_backup_done: +#endif + + post_code(0x3d) + + /* Clear boot_complete flag. */ + xorl %ebp, %ebp +__main: + post_code(POST_PREPARE_RAMSTAGE) + cld /* Clear direction flag. */ + + movl %ebp, %esi + + movl $ROMSTAGE_STACK, %esp + movl %esp, %ebp + pushl %esi + call copy_and_run + +.Lhlt: + post_code(POST_DEAD_CODE) + hlt + jmp .Lhlt + diff --git a/src/mainboard/emulation/qemu-x86/devicetree.cb b/src/mainboard/emulation/qemu-x86/devicetree.cb index 4c64d4a..50f4b11 100644 --- a/src/mainboard/emulation/qemu-x86/devicetree.cb +++ b/src/mainboard/emulation/qemu-x86/devicetree.cb @@ -7,7 +7,7 @@ chip mainboard/emulation/qemu-x86 device pci 01.1 on end register "ide0_enable" = "1" register "ide1_enable" = "1" + register "gpo" = "0x7fffbbff" end - end end diff --git a/src/mainboard/emulation/qemu-x86/dsdt.asl b/src/mainboard/emulation/qemu-x86/dsdt.asl new file mode 100644 index 0000000..d559aaf --- /dev/null +++ b/src/mainboard/emulation/qemu-x86/dsdt.asl @@ -0,0 +1,958 @@ +/* + * Bochs/QEMU ACPI DSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20090419 // OEM revision +) +{ + +/**************************************************************** + * Debugging + ****************************************************************/ + + Scope (\) + { + /* Debug Output */ + OperationRegion (DBG, SystemIO, 0x0402, 0x01) + Field (DBG, ByteAcc, NoLock, Preserve) + { + DBGB, 8, + } + + /* Debug method - use this method to send output to the QEMU + * BIOS debug port. This method handles strings, integers, + * and buffers. For example: DBUG("abc") DBUG(0x123) */ + Method(DBUG, 1) { + ToHexString(Arg0, Local0) + ToBuffer(Local0, Local0) + Subtract(SizeOf(Local0), 1, Local1) + Store(Zero, Local2) + While (LLess(Local2, Local1)) { + Store(DerefOf(Index(Local0, Local2)), DBGB) + Increment(Local2) + } + Store(0x0A, DBGB) + } + } + +/**************************************************************** + * Processor + ****************************************************************/ + + Processor (CPAA, 0xAA, 0x0000b010, 0x06) { + Name (ID, 0xAA) + Name (_HID, "ACPI0007") + Method(_MAT, 0) { + Return(\_SB.CPMA(ID)) + } + Method (_STA, 0) { + Return(\_SB.CPST(ID)) + } + Method (_EJ0, 1, NotSerialized) { + \_SB.CPEJ(ID, Arg0) + } + } + +/**************************************************************** + * PCI Bus definition + ****************************************************************/ + + Scope(\_SB) { + Device(PCI0) { + Name (_HID, EisaId ("PNP0A03")) + Name (_ADR, 0x00) + Name (_UID, 1) + Name(_PRT, Package() { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ +#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \ + Package() { nr##ffff, 0, lnk0, 0 }, \ + Package() { nr##ffff, 1, lnk1, 0 }, \ + Package() { nr##ffff, 2, lnk2, 0 }, \ + Package() { nr##ffff, 3, lnk3, 0 } + +#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC) +#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD) +#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA) +#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB) + prt_slot0(0x0000), + /* Device 1 is power mgmt device, and can only use irq 9 */ + prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD), + prt_slot2(0x0002), + prt_slot3(0x0003), + prt_slot0(0x0004), + prt_slot1(0x0005), + prt_slot2(0x0006), + prt_slot3(0x0007), + prt_slot0(0x0008), + prt_slot1(0x0009), + prt_slot2(0x000a), + prt_slot3(0x000b), + prt_slot0(0x000c), + prt_slot1(0x000d), + prt_slot2(0x000e), + prt_slot3(0x000f), + prt_slot0(0x0010), + prt_slot1(0x0011), + prt_slot2(0x0012), + prt_slot3(0x0013), + prt_slot0(0x0014), + prt_slot1(0x0015), + prt_slot2(0x0016), + prt_slot3(0x0017), + prt_slot0(0x0018), + prt_slot1(0x0019), + prt_slot2(0x001a), + prt_slot3(0x001b), + prt_slot0(0x001c), + prt_slot1(0x001d), + prt_slot2(0x001e), + prt_slot3(0x001f), + }) + + OperationRegion(PCST, SystemIO, 0xae00, 0x08) + Field (PCST, DWordAcc, NoLock, WriteAsZeros) + { + PCIU, 32, + PCID, 32, + } + + OperationRegion(SEJ, SystemIO, 0xae08, 0x04) + Field (SEJ, DWordAcc, NoLock, WriteAsZeros) + { + B0EJ, 32, + } + + Name (CRES, ResourceTemplate () + { + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x00FF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0100, // Address Length + ,, ) + IO (Decode16, + 0x0CF8, // Address Range Minimum + 0x0CF8, // Address Range Maximum + 0x01, // Address Alignment + 0x08, // Address Length + ) + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x0CF7, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0CF8, // Address Length + ,, , TypeStatic) + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0D00, // Address Range Minimum + 0xFFFF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0xF300, // Address Length + ,, , TypeStatic) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x000A0000, // Address Range Minimum + 0x000BFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00020000, // Address Length + ,, , AddressRangeMemory, TypeStatic) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0xE0000000, // Address Range Minimum + 0xFEBFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x1EC00000, // Address Length + ,, PW32, AddressRangeMemory, TypeStatic) + }) + Name (CR64, ResourceTemplate () + { + QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x8000000000, // Address Range Minimum + 0xFFFFFFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x8000000000, // Address Length + ,, PW64, AddressRangeMemory, TypeStatic) + }) + Method (_CRS, 0) + { + /* see see acpi.h, struct bfld */ + External (BDAT, OpRegionObj) + Field(BDAT, QWordAcc, NoLock, Preserve) { + P0S, 64, + P0E, 64, + P0L, 64, + P1S, 64, + P1E, 64, + P1L, 64, + } + Field(BDAT, DWordAcc, NoLock, Preserve) { + P0SL, 32, + P0SH, 32, + P0EL, 32, + P0EH, 32, + P0LL, 32, + P0LH, 32, + P1SL, 32, + P1SH, 32, + P1EL, 32, + P1EH, 32, + P1LL, 32, + P1LH, 32, + } + + /* fixup 32bit pci io window */ + CreateDWordField (CRES,\_SB.PCI0.PW32._MIN, PS32) + CreateDWordField (CRES,\_SB.PCI0.PW32._MAX, PE32) + CreateDWordField (CRES,\_SB.PCI0.PW32._LEN, PL32) + Store (P0SL, PS32) + Store (P0EL, PE32) + Store (P0LL, PL32) + + If (LAnd(LEqual(P1SL, 0x00), LEqual(P1SH, 0x00))) { + Return (CRES) + } Else { + /* fixup 64bit pci io window */ + CreateQWordField (CR64,\_SB.PCI0.PW64._MIN, PS64) + CreateQWordField (CR64,\_SB.PCI0.PW64._MAX, PE64) + CreateQWordField (CR64,\_SB.PCI0.PW64._LEN, PL64) + Store (P1S, PS64) + Store (P1E, PE64) + Store (P1L, PL64) + /* add window and return result */ + ConcatenateResTemplate (CRES, CR64, Local0) + Return (Local0) + } + } + } + } + + +/**************************************************************** + * HPET + ****************************************************************/ + + Scope(\_SB) { + Device(HPET) { + Name(_HID, EISAID("PNP0103")) + Name(_UID, 0) + OperationRegion(HPTM, SystemMemory , 0xFED00000, 0x400) + Field(HPTM, DWordAcc, Lock, Preserve) { + VEND, 32, + PRD, 32, + } + Method (_STA, 0, NotSerialized) { + Store (VEND, Local0) + Store (PRD, Local1) + ShiftRight(Local0, 16, Local0) + If (LOr (LEqual(Local0, 0), LEqual(Local0, 0xffff))) { + Return (0x0) + } + If (LOr (LEqual(Local1, 0), LGreater(Local1, 100000000))) { + Return (0x0) + } + Return (0x0F) + } + Name(_CRS, ResourceTemplate() { + DWordMemory( + ResourceConsumer, PosDecode, MinFixed, MaxFixed, + NonCacheable, ReadWrite, + 0x00000000, + 0xFED00000, + 0xFED003FF, + 0x00000000, + 0x00000400 /* 1K memory: FED00000 - FED003FF */ + ) + }) + } + } + + +/**************************************************************** + * VGA + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device (VGA) { + Name (_ADR, 0x00020000) + OperationRegion(PCIC, PCI_Config, Zero, 0x4) + Field(PCIC, DWordAcc, NoLock, Preserve) { + VEND, 32 + } + Method (_S1D, 0, NotSerialized) + { + Return (0x00) + } + Method (_S2D, 0, NotSerialized) + { + Return (0x00) + } + Method (_S3D, 0, NotSerialized) + { + If (LEqual(VEND, 0x1001b36)) { + Return (0x03) // QXL + } Else { + Return (0x00) + } + } + } + } + + +/**************************************************************** + * PIIX3 ISA bridge + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device (ISA) { + Name (_ADR, 0x00010000) + + /* PIIX PCI to ISA irq remapping */ + OperationRegion (P40C, PCI_Config, 0x60, 0x04) + } + } + + +/**************************************************************** + * SuperIO devices (kbd, mouse, etc.) + ****************************************************************/ + + Scope(\_SB.PCI0.ISA) { + /* Real-time clock */ + Device (RTC) + { + Name (_HID, EisaId ("PNP0B00")) + Name (_CRS, ResourceTemplate () + { + IO (Decode16, 0x0070, 0x0070, 0x10, 0x02) + IRQNoFlags () {8} + IO (Decode16, 0x0072, 0x0072, 0x02, 0x06) + }) + } + + /* Keyboard seems to be important for WinXP install */ + Device (KBD) + { + Name (_HID, EisaId ("PNP0303")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) + } + + Method (_CRS, 0, NotSerialized) + { + Name (TMP, ResourceTemplate () + { + IO (Decode16, + 0x0060, // Address Range Minimum + 0x0060, // Address Range Maximum + 0x01, // Address Alignment + 0x01, // Address Length + ) + IO (Decode16, + 0x0064, // Address Range Minimum + 0x0064, // Address Range Maximum + 0x01, // Address Alignment + 0x01, // Address Length + ) + IRQNoFlags () + {1} + }) + Return (TMP) + } + } + + /* PS/2 mouse */ + Device (MOU) + { + Name (_HID, EisaId ("PNP0F13")) + Method (_STA, 0, NotSerialized) + { + Return (0x0f) + } + + Method (_CRS, 0, NotSerialized) + { + Name (TMP, ResourceTemplate () + { + IRQNoFlags () {12} + }) + Return (TMP) + } + } + + /* PS/2 floppy controller */ + Device (FDC0) + { + Name (_HID, EisaId ("PNP0700")) + Method (_STA, 0, NotSerialized) + { + Return (0x0F) + } + Method (_CRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () + { + IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04) + IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01) + IRQNoFlags () {6} + DMA (Compatibility, NotBusMaster, Transfer8) {2} + }) + Return (BUF0) + } + } + + /* Parallel port */ + Device (LPT) + { + Name (_HID, EisaId ("PNP0400")) + Method (_STA, 0, NotSerialized) + { + Store (\_SB.PCI0.PX13.DRSA, Local0) + And (Local0, 0x80000000, Local0) + If (LEqual (Local0, 0)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + Method (_CRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () + { + IO (Decode16, 0x0378, 0x0378, 0x08, 0x08) + IRQNoFlags () {7} + }) + Return (BUF0) + } + } + + /* Serial Ports */ + Device (COM1) + { + Name (_HID, EisaId ("PNP0501")) + Name (_UID, 0x01) + Method (_STA, 0, NotSerialized) + { + Store (\_SB.PCI0.PX13.DRSC, Local0) + And (Local0, 0x08000000, Local0) + If (LEqual (Local0, 0)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + Method (_CRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () + { + IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08) + IRQNoFlags () {4} + }) + Return (BUF0) + } + } + + Device (COM2) + { + Name (_HID, EisaId ("PNP0501")) + Name (_UID, 0x02) + Method (_STA, 0, NotSerialized) + { + Store (\_SB.PCI0.PX13.DRSC, Local0) + And (Local0, 0x80000000, Local0) + If (LEqual (Local0, 0)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + Method (_CRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () + { + IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08) + IRQNoFlags () {3} + }) + Return (BUF0) + } + } + } + + +/**************************************************************** + * PIIX4 PM + ****************************************************************/ + + Scope(\_SB.PCI0) { + Device (PX13) { + Name (_ADR, 0x00010003) + + OperationRegion (P13C, PCI_Config, 0x5c, 0x24) + Field (P13C, DWordAcc, NoLock, Preserve) + { + DRSA, 32, + DRSB, 32, + DRSC, 32, + DRSE, 32, + DRSF, 32, + DRSG, 32, + DRSH, 32, + DRSI, 32, + DRSJ, 32 + } + } + } + + +/**************************************************************** + * PCI hotplug + ****************************************************************/ + + Scope(\_SB.PCI0) { + /* Methods called by bulk generated PCI devices below */ + + /* Methods called by hotplug devices */ + Method (PCEJ, 1, NotSerialized) { + // _EJ0 method - eject callback + Store(ShiftLeft(1, Arg0), B0EJ) + Return (0x0) + } + + /* Hotplug notification method supplied by SSDT */ + External (\_SB.PCI0.PCNT, MethodObj) + + /* PCI hotplug notify method */ + Method(PCNF, 0) { + // Local0 = iterator + Store (Zero, Local0) + While (LLess(Local0, 31)) { + Increment(Local0) + If (And(PCIU, ShiftLeft(1, Local0))) { + PCNT(Local0, 1) + } + If (And(PCID, ShiftLeft(1, Local0))) { + PCNT(Local0, 3) + } + } + Return(One) + } + + } + + +/**************************************************************** + * PCI IRQs + ****************************************************************/ + + Scope(\_SB) { + Field (PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) + { + PRQ0, 8, + PRQ1, 8, + PRQ2, 8, + PRQ3, 8 + } + + Method (IQST, 1, NotSerialized) { + // _STA method - get status + If (And (0x80, Arg0)) { + Return (0x09) + } + Return (0x0B) + } + Method (IQCR, 1, NotSerialized) { + // _CRS method - get current settings + Name (PRR0, ResourceTemplate () + { + Interrupt (, Level, ActiveHigh, Shared) + { 0 } + }) + CreateDWordField (PRR0, 0x05, PRRI) + If (LLess (Arg0, 0x80)) { + Store (Arg0, PRRI) + } + Return (PRR0) + } + // _DIS method - disable interrupt +#define DISIRQ(PRQVAR) \ + Or(PRQVAR, 0x80, PRQVAR) \ + // _SRS method - set interrupt +#define SETIRQ(PRQVAR, IRQINFO) \ + CreateDWordField (IRQINFO, 0x05, PRRI) \ + Store (PRRI, PRQVAR) + + Device(LNKA) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name(_UID, 1) + Name(_PRS, ResourceTemplate(){ + Interrupt (, Level, ActiveHigh, Shared) + { 5, 10, 11 } + }) + Method (_STA, 0, NotSerialized) { Return (IQST(PRQ0)) } + Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ0) } + Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ0)) } + Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ0, Arg0) } + } + Device(LNKB) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name(_UID, 2) + Name(_PRS, ResourceTemplate(){ + Interrupt (, Level, ActiveHigh, Shared) + { 5, 10, 11 } + }) + Method (_STA, 0, NotSerialized) { Return (IQST(PRQ1)) } + Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ1) } + Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ1)) } + Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ1, Arg0) } + } + Device(LNKC) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name(_UID, 3) + Name(_PRS, ResourceTemplate() { + Interrupt (, Level, ActiveHigh, Shared) + { 5, 10, 11 } + }) + Method (_STA, 0, NotSerialized) { Return (IQST(PRQ2)) } + Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ2) } + Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ2)) } + Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ2, Arg0) } + } + Device(LNKD) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name(_UID, 4) + Name(_PRS, ResourceTemplate() { + Interrupt (, Level, ActiveHigh, Shared) + { 5, 10, 11 } + }) + Method (_STA, 0, NotSerialized) { Return (IQST(PRQ3)) } + Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ3) } + Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ3)) } + Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ3, Arg0) } + } + Device(LNKS) { + Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name(_UID, 5) + Name(_PRS, ResourceTemplate() { + Interrupt (, Level, ActiveHigh, Shared) + { 9 } + }) + Method (_STA, 0, NotSerialized) { Return (IQST(PRQ0)) } + Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ0) } + Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ0)) } + } + } + +/**************************************************************** + * CPU hotplug + ****************************************************************/ + + Scope(\_SB) { + /* Objects filled in by run-time generated SSDT */ + External(NTFY, MethodObj) + External(CPON, PkgObj) + + /* Methods called by run-time generated SSDT Processor objects */ + Method (CPMA, 1, NotSerialized) { + // _MAT method - create an madt apic buffer + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + // Local1 = Buffer (in madt apic form) to return + Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1) + // Update the processor id, lapic id, and enable/disable status + Store(Arg0, Index(Local1, 2)) + Store(Arg0, Index(Local1, 3)) + Store(Local0, Index(Local1, 4)) + Return (Local1) + } + Method (CPST, 1, NotSerialized) { + // _STA method - return ON status of cpu + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + If (Local0) { Return(0xF) } Else { Return(0x0) } + } + Method (CPEJ, 2, NotSerialized) { + // _EJ0 method - eject callback + Sleep(200) + } + + /* CPU hotplug notify method */ + OperationRegion(PRST, SystemIO, 0xaf00, 32) + Field (PRST, ByteAcc, NoLock, Preserve) + { + PRS, 256 + } + Method(PRSC, 0) { + // Local5 = active cpu bitmap + Store (PRS, Local5) + // Local2 = last read byte from bitmap + Store (Zero, Local2) + // Local0 = Processor ID / APIC ID iterator + Store (Zero, Local0) + While (LLess(Local0, SizeOf(CPON))) { + // Local1 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Local0)), Local1) + If (And(Local0, 0x07)) { + // Shift down previously read bitmap byte + ShiftRight(Local2, 1, Local2) + } Else { + // Read next byte from cpu bitmap + Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2) + } + // Local3 = active state for this cpu + Store(And(Local2, 1), Local3) + + If (LNotEqual(Local1, Local3)) { + // State change - update CPON with new state + Store(Local3, Index(CPON, Local0)) + // Do CPU notify + If (LEqual(Local3, 1)) { + NTFY(Local0, 1) + } Else { + NTFY(Local0, 3) + } + } + Increment(Local0) + } + Return(One) + } + } + + +/**************************************************************** + * General purpose events + ****************************************************************/ + + Scope (\_GPE) + { + Name(_HID, "ACPI0006") + + Method(_L00) { + } + Method(_E01) { + // PCI hotplug event + \_SB.PCI0.PCNF() + } + Method(_E02) { + // CPU hotplug event + \_SB.PRSC() + } + Method(_L03) { + } + Method(_L04) { + } + Method(_L05) { + } + Method(_L06) { + } + Method(_L07) { + } + Method(_L08) { + } + Method(_L09) { + } + Method(_L0A) { + } + Method(_L0B) { + } + Method(_L0C) { + } + Method(_L0D) { + } + Method(_L0E) { + } + Method(_L0F) { + } + } + + + Scope(\_SB.PCI0) { + Device (S01) { + Name (_ADR, 0x010000) + Method (_EJ0, 1) { PCEJ(0x01) } Name (_SUN, 0x01) } + Device (S02) { + Name (_ADR, 0x020000) + Method (_EJ0, 1) { PCEJ(0x02) } Name (_SUN, 0x02) } + Device (S03) { + Name (_ADR, 0x030000) + Method (_EJ0, 1) { PCEJ(0x03) } Name (_SUN, 0x03) } + Device (S04) { + Name (_ADR, 0x040000) + Method (_EJ0, 1) { PCEJ(0x04) } Name (_SUN, 0x04) } + Device (S05) { + Name (_ADR, 0x050000) + Method (_EJ0, 1) { PCEJ(0x05) } Name (_SUN, 0x05) } + Device (S06) { + Name (_ADR, 0x060000) + Method (_EJ0, 1) { PCEJ(0x06) } Name (_SUN, 0x06) } + Device (S07) { + Name (_ADR, 0x070000) + Method (_EJ0, 1) { PCEJ(0x07) } Name (_SUN, 0x07) } + Device (S08) { + Name (_ADR, 0x080000) + Method (_EJ0, 1) { PCEJ(0x08) } Name (_SUN, 0x08) } + Device (S09) { + Name (_ADR, 0x090000) + Method (_EJ0, 1) { PCEJ(0x09) } Name (_SUN, 0x09) } + Device (S0a) { + Name (_ADR, 0x0a0000) + Method (_EJ0, 1) { PCEJ(0x0a) } Name (_SUN, 0x0a) } + Device (S0b) { + Name (_ADR, 0x0b0000) + Method (_EJ0, 1) { PCEJ(0x0b) } Name (_SUN, 0x0b) } + Device (S0c) { + Name (_ADR, 0x0c0000) + Method (_EJ0, 1) { PCEJ(0x0c) } Name (_SUN, 0x0c) } + Device (S0d) { + Name (_ADR, 0x0d0000) + Method (_EJ0, 1) { PCEJ(0x0d) } Name (_SUN, 0x0d) } + Device (S0e) { + Name (_ADR, 0x0e0000) + Method (_EJ0, 1) { PCEJ(0x0e) } Name (_SUN, 0x0e) } + Device (S0f) { + Name (_ADR, 0x0f0000) + Method (_EJ0, 1) { PCEJ(0x0f) } Name (_SUN, 0x0f) } + Device (S10) { + Name (_ADR, 0x100000) + Method (_EJ0, 1) { PCEJ(0x10) } Name (_SUN, 0x10) } + Device (S11) { + Name (_ADR, 0x110000) + Method (_EJ0, 1) { PCEJ(0x11) } Name (_SUN, 0x11) } + Device (S12) { + Name (_ADR, 0x120000) + Method (_EJ0, 1) { PCEJ(0x12) } Name (_SUN, 0x12) } + Device (S13) { + Name (_ADR, 0x130000) + Method (_EJ0, 1) { PCEJ(0x13) } Name (_SUN, 0x13) } + Device (S14) { + Name (_ADR, 0x140000) + Method (_EJ0, 1) { PCEJ(0x14) } Name (_SUN, 0x14) } + Device (S15) { + Name (_ADR, 0x150000) + Method (_EJ0, 1) { PCEJ(0x15) } Name (_SUN, 0x15) } + Device (S16) { + Name (_ADR, 0x160000) + Method (_EJ0, 1) { PCEJ(0x16) } Name (_SUN, 0x16) } + Device (S17) { + Name (_ADR, 0x170000) + Method (_EJ0, 1) { PCEJ(0x17) } Name (_SUN, 0x17) } + Device (S18) { + Name (_ADR, 0x180000) + Method (_EJ0, 1) { PCEJ(0x18) } Name (_SUN, 0x18) } + Device (S19) { + Name (_ADR, 0x190000) + Method (_EJ0, 1) { PCEJ(0x19) } Name (_SUN, 0x19) } + Device (S1a) { + Name (_ADR, 0x1a0000) + Method (_EJ0, 1) { PCEJ(0x1a) } Name (_SUN, 0x1a) } + Device (S1b) { + Name (_ADR, 0x1b0000) + Method (_EJ0, 1) { PCEJ(0x1b) } Name (_SUN, 0x1b) } + Device (S1c) { + Name (_ADR, 0x1c0000) + Method (_EJ0, 1) { PCEJ(0x1c) } Name (_SUN, 0x1c) } + Device (S1d) { + Name (_ADR, 0x1d0000) + Method (_EJ0, 1) { PCEJ(0x1d) } Name (_SUN, 0x1d) } + Device (S1e) { + Name (_ADR, 0x1e0000) + Method (_EJ0, 1) { PCEJ(0x1e) } Name (_SUN, 0x1e) } + Device (S1f) { + Name (_ADR, 0x1f0000) + Method (_EJ0, 1) { PCEJ(0x1f) } Name (_SUN, 0x1f) } + Method(PCNT, 2) { + If (LEqual(Arg0, 0x01)) { Notify(S01, Arg1) } + If (LEqual(Arg0, 0x02)) { Notify(S02, Arg1) } + If (LEqual(Arg0, 0x03)) { Notify(S03, Arg1) } + If (LEqual(Arg0, 0x04)) { Notify(S04, Arg1) } + If (LEqual(Arg0, 0x05)) { Notify(S05, Arg1) } + If (LEqual(Arg0, 0x06)) { Notify(S06, Arg1) } + If (LEqual(Arg0, 0x07)) { Notify(S07, Arg1) } + If (LEqual(Arg0, 0x08)) { Notify(S08, Arg1) } + If (LEqual(Arg0, 0x09)) { Notify(S09, Arg1) } + If (LEqual(Arg0, 0x0a)) { Notify(S0a, Arg1) } + If (LEqual(Arg0, 0x0b)) { Notify(S0b, Arg1) } + If (LEqual(Arg0, 0x0c)) { Notify(S0c, Arg1) } + If (LEqual(Arg0, 0x0d)) { Notify(S0d, Arg1) } + If (LEqual(Arg0, 0x0e)) { Notify(S0e, Arg1) } + If (LEqual(Arg0, 0x0f)) { Notify(S0f, Arg1) } + If (LEqual(Arg0, 0x10)) { Notify(S10, Arg1) } + If (LEqual(Arg0, 0x11)) { Notify(S11, Arg1) } + If (LEqual(Arg0, 0x12)) { Notify(S12, Arg1) } + If (LEqual(Arg0, 0x13)) { Notify(S13, Arg1) } + If (LEqual(Arg0, 0x14)) { Notify(S14, Arg1) } + If (LEqual(Arg0, 0x15)) { Notify(S15, Arg1) } + If (LEqual(Arg0, 0x16)) { Notify(S16, Arg1) } + If (LEqual(Arg0, 0x17)) { Notify(S17, Arg1) } + If (LEqual(Arg0, 0x18)) { Notify(S18, Arg1) } + If (LEqual(Arg0, 0x19)) { Notify(S19, Arg1) } + If (LEqual(Arg0, 0x1a)) { Notify(S1a, Arg1) } + If (LEqual(Arg0, 0x1b)) { Notify(S1b, Arg1) } + If (LEqual(Arg0, 0x1c)) { Notify(S1c, Arg1) } + If (LEqual(Arg0, 0x1d)) { Notify(S1d, Arg1) } + If (LEqual(Arg0, 0x1e)) { Notify(S1e, Arg1) } + If (LEqual(Arg0, 0x1f)) { Notify(S1f, Arg1) } + } + } + + Scope(\) { + Name (_S3, Package (0x04) + { + One, + One, + Zero, + Zero + }) + Name (_S4, Package (0x04) + { + 0x2, + 0x2, + Zero, + Zero + }) + Name (_S5, Package (0x04) + { + Zero, + Zero, + Zero, + Zero + }) + } +} diff --git a/src/mainboard/emulation/qemu-x86/mainboard.c b/src/mainboard/emulation/qemu-x86/mainboard.c index 96adfa7..44efba9 100644 --- a/src/mainboard/emulation/qemu-x86/mainboard.c +++ b/src/mainboard/emulation/qemu-x86/mainboard.c @@ -1,3 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Stefan Reinauer + * Copyright (C) 2010 Kevin O'Connor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include #include #include @@ -26,8 +46,8 @@ static void qemu_nb_init(device_t dev) /* The PIRQ table is not working well for interrupt routing purposes. * so we'll just set the IRQ directly. - */ - printk(BIOS_INFO, "setting ethernet\n"); + */ + printk(BIOS_INFO, "Setting up ethernet...\n"); pci_assign_irqs(0, 3, enetIrqs); } diff --git a/src/mainboard/emulation/qemu-x86/memory.c b/src/mainboard/emulation/qemu-x86/memory.c new file mode 100644 index 0000000..e4b3b98 --- /dev/null +++ b/src/mainboard/emulation/qemu-x86/memory.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#define CMOS_ADDR_PORT 0x70 +#define CMOS_DATA_PORT 0x71 +#define HIGH_RAM_ADDR 0x35 +#define LOW_RAM_ADDR 0x34 + +static unsigned long qemu_get_memory_size(void) +{ + unsigned long tomk; + outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT); + tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14; + outb (LOW_RAM_ADDR, CMOS_ADDR_PORT); + tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6; + tomk += 16 * 1024; + return tomk; +} + +unsigned long get_top_of_ram(void); +unsigned long get_top_of_ram(void) +{ + return qemu_get_memory_size() * 1024; +} + +struct cbmem_entry *get_cbmem_toc(void) +{ + return (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE); +} diff --git a/src/mainboard/emulation/qemu-x86/northbridge.c b/src/mainboard/emulation/qemu-x86/northbridge.c index 16dcc3b..6d73585 100644 --- a/src/mainboard/emulation/qemu-x86/northbridge.c +++ b/src/mainboard/emulation/qemu-x86/northbridge.c @@ -14,21 +14,7 @@ #include #endif -#define CMOS_ADDR_PORT 0x70 -#define CMOS_DATA_PORT 0x71 -#define HIGH_RAM_ADDR 0x35 -#define LOW_RAM_ADDR 0x34 - -static unsigned long qemu_get_memory_size(void) -{ - unsigned long tomk; - outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT); - tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14; - outb (LOW_RAM_ADDR, CMOS_ADDR_PORT); - tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6; - tomk += 16 * 1024; - return tomk; -} +#include "memory.c" static void cpu_pci_domain_set_resources(device_t dev) { diff --git a/src/mainboard/emulation/qemu-x86/romstage.c b/src/mainboard/emulation/qemu-x86/romstage.c index 33a0fcc..be14db9 100644 --- a/src/mainboard/emulation/qemu-x86/romstage.c +++ b/src/mainboard/emulation/qemu-x86/romstage.c @@ -1,3 +1,22 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include #include #include @@ -7,17 +26,42 @@ #include #include #include +#include +#include #include "drivers/pc80/udelay_io.c" #include "lib/delay.c" #include "cpu/x86/lapic/boot_cpu.c" -static void main(void) +#include "memory.c" + +void main(unsigned long bist) { + int cbmem_was_initted; + /* init_timer(); */ post_code(0x05); console_init(); + /* Halt if there was a built in self test failure */ + report_bist_failure(bist); + //print_pci_devices(); //dump_pci_devices(); + +#if CONFIG_EARLY_CBMEM_INIT + cbmem_was_initted = !cbmem_initialize(); +#else + cbmem_was_initted = cbmem_reinit((uint64_t) (get_top_of_ram() + - HIGH_MEMORY_SIZE)); +#endif +#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(rdtsc()); + timestamp_add_now(TS_START_ROMSTAGE); +#endif +#if CONFIG_CONSOLE_CBMEM + /* Keep this the last thing this function does. */ + cbmemc_reinit(); +#endif + } From peter at stuge.se Mon Jan 7 22:40:20 2013 From: peter at stuge.se (Peter Stuge) Date: Mon, 7 Jan 2013 22:40:20 +0100 Subject: [coreboot] [SPAM] Re: Feedback On Coreboot: the Solution to the SecureBoot Fiasco In-Reply-To: <20130107203531.GA23416@countzero.vandewege.net> References: <59005.1357568941@tinet.org> <20130107203531.GA23416@countzero.vandewege.net> Message-ID: <20130107214020.25380.qmail@stuge.se> Ward Vandewege wrote: > This. It's called 'remote attestation' > (https://en.wikipedia.org/wiki/Trusted_Computing#Remote_attestation). > An obvious (first?) application will be your bank, which will refuse > you access to their online banking system unless you run a 'trusted' > software stack. Yes and no - software is not the core business of banks, so they most likely prefer *not* to have to deal with these things, including customer support. They simply buy solutions, such as Vasco DigiPass, and/or crypto chip cards. A progressive bank might have an IT department that actually develops an iOS app, but I think that will be about it. There are some highlights however; In Sweden, banks accept government-issued eIDs for login, as long as they follow the BankID coalition spec. There is an open source and free software implementation of this, which does allow to use any token or chip card supported by OpenSC. In Germany, banks support a public API for home banking, for which it also exists at least one open source and free software implementation that works fine with the chip card issued by the bank again via OpenSC. //Peter From gerrit at coreboot.org Mon Jan 7 22:41:53 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Mon, 7 Jan 2013 22:41:53 +0100 Subject: [coreboot] New patch to review for coreboot: 1560718 cbmem utility: Add option to dump cbmem console References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2114 -gerrit commit 1560718f8d10dd0394e3df6f7bdc4fee54034ce5 Author: Stefan Reinauer Date: Mon Jan 7 13:37:12 2013 -0800 cbmem utility: Add option to dump cbmem console This adds an option to the cbmem utility to dump the cbmem console. To keep the utility backwards compatible, specifying -c disables printing of time stamps. To print both console and time stamps, run the utility with -ct Change-Id: Idd2dbf32c3c44f857c2f41e6c817c5ab13155d6f Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index df00684..cc98e56 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -283,6 +283,29 @@ static void dump_timestamps(void) unmap_memory(); } +/* dump the cbmem console */ +static void dump_console(void) +{ + void *console_p; + + if (console.tag != LB_TAG_CBMEM_CONSOLE) { + fprintf(stderr, "No console found in coreboot table.\n"); + return; + } + + console_p = map_memory((unsigned long)console.cbmem_addr); + /* The in-memory format of the console area is: + * u32 size + * u32 cursor + * char console[size] + * Hence we have to add 8 to get to the actual console string. + */ + printf("%s", (char *)console_p + 8); + + unmap_memory(); +} + + void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); @@ -303,6 +326,9 @@ void print_usage(const char *name) { printf("usage: %s [-vh?]\n", name); printf("\n" + " -c | --console: verbose (debugging) output\n" + " -t | --timestamps: verbose (debugging) output\n" + " -V | --verbose: verbose (debugging) output\n" " -v | --version: print the version\n" " -h | --help: print this help\n" "\n"); @@ -314,18 +340,30 @@ int main(int argc, char** argv) int j; static const int possible_base_addresses[] = { 0, 0xf0000 }; - int print_timestamps = 1; + int print_defaults = 1; + int print_console = 0; + int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { + {"console", 0, 0, 'c'}, + {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "Vvh?", + while ((opt = getopt_long(argc, argv, "ctVvh?", long_options, &option_index)) != EOF) { switch (opt) { + case 'c': + print_console = 1; + print_defaults = 0; + break; + case 't': + print_timestamps = 1; + print_defaults = 0; + break; case 'V': verbose = 1; break; @@ -355,7 +393,10 @@ int main(int argc, char** argv) break; } - if (print_timestamps) + if (print_console) + dump_console(); + + if (print_defaults || print_timestamps) dump_timestamps(); close(fd); From gerrit at coreboot.org Mon Jan 7 22:41:53 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Mon, 7 Jan 2013 22:41:53 +0100 Subject: [coreboot] New patch to review for coreboot: 1d064f3 cbmem utility: drop obsolete python version References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2115 -gerrit commit 1d064f3d704f43df3f03b580076f17ce96275f42 Author: Stefan Reinauer Date: Mon Jan 7 13:39:43 2013 -0800 cbmem utility: drop obsolete python version The first version of the cbmem utility was written in python, but it had issues with 64bit systems and other little hick ups. Since the C version has much fewer dependencies (no python needed on target system), and it works in all corner cases, drop the python version. Change-Id: Ida3d6c9bb46f6d826f45538e4ceaa4fc1e771ff5 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.py | 259 ---------------------------------------------------- 1 file changed, 259 deletions(-) diff --git a/util/cbmem/cbmem.py b/util/cbmem/cbmem.py deleted file mode 100755 index 70ccc00..0000000 --- a/util/cbmem/cbmem.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/python -# -# cbmem.py - Linux space CBMEM contents parser -# -# Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -''' -Parse and display CBMEM contents. - -This module is meant to run on systems with coreboot based firmware. - -When started, it determines the amount of DRAM installed on the system, and -then scans the top area of DRAM (right above the available memory size) -looking for the CBMEM base signature at locations aligned at 0x20000 -boundaries. - -Once it finds the CBMEM signature, the utility parses the contents, reporting -the section IDs/sizes and also reporting the contents of the tiemstamp and -console sections. -''' - -import mmap -import struct -import sys - -def get_phys_mem(addr, size): - '''Read size bytes from address addr by mmaping /dev/mem''' - - mf = open("/dev/mem") - delta = addr % 4096 - mm = mmap.mmap(mf.fileno(), size + delta, - mmap.MAP_PRIVATE, offset=(addr - delta)) - buf = mm.read(size + delta) - mf.close() - return buf[delta:] - -# This class and metaclass make it easier to define and access structures -# which live in physical memory. To use them, inherit from CStruct and define -# a class member called struct_members which is a tuple of pairs. The first -# item in the pair is the type format specifier that should be used with -# struct.unpack to read that member from memory. The second item is the name -# that member should have in the resulting object. - -class MetaCStruct(type): - def __init__(cls, name, bases, dct): - struct_members = dct["struct_members"] - cls.struct_fmt = "<" - for char, name in struct_members: - cls.struct_fmt += char - cls.struct_len = struct.calcsize(cls.struct_fmt) - super(MetaCStruct, cls).__init__(name, bases, dct) - -class CStruct(object): - __metaclass__ = MetaCStruct - struct_members = () - - def __init__(self, addr): - self.raw_memory = get_phys_mem(addr, self.struct_len) - values = struct.unpack(self.struct_fmt, self.raw_memory) - names = (name for char, name in self.struct_members) - for name, value in zip(names, values): - setattr(self, name, value) - -def normalize_timer(value, freq): - '''Convert timer reading into microseconds. - - Get the free running clock counter value, divide it by the clock frequency - and multiply by 1 million to get reading in microseconds. - - Then convert the value into an ASCII string with groups of three digits - separated by commas. - - Inputs: - value: int, the clock reading - freq: float, the clock frequency - - Returns: - A string presenting 'value' in microseconds. - ''' - - result = [] - value = int(value * 1000000.0 / freq) - svalue = '%d' % value - vlength = len(svalue) - remainder = vlength % 3 - if remainder: - result.append(svalue[0:remainder]) - while remainder < vlength: - result.append(svalue[remainder:remainder+3]) - remainder = remainder + 3 - return ','.join(result) - -def get_cpu_freq(): - '''Retrieve CPU frequency from sysfs. - - Use /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq as the source. - ''' - freq_str = open('/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq' - ).read() - # Convert reading into Hertz - return float(freq_str) * 1000.0 - -def process_timers(base): - '''Scan the array of timestamps found in CBMEM at address base. - - For each timestamp print the timer ID and the value in microseconds. - ''' - - class TimestampHeader(CStruct): - struct_members = ( - ("Q", "base_time"), - ("L", "max_entr"), - ("L", "entr") - ) - - class TimestampEntry(CStruct): - struct_members = ( - ("L", "timer_id"), - ("Q", "timer_value") - ) - - header = TimestampHeader(base) - print('\ntime base %d, total entries %d' % (header.base_time, header.entr)) - clock_freq = get_cpu_freq() - base = base + header.struct_len - prev_time = 0 - for i in range(header.entr): - timestamp = TimestampEntry(base) - print '%d:%s ' % (timestamp.timer_id, - normalize_timer(timestamp.timer_value, clock_freq)), - if prev_time: - print '(%s)' % normalize_timer( - timestamp.timer_value - prev_time, clock_freq), - prev_time = timestamp.timer_value - print - base = base + timestamp.struct_len - print - -def process_console(base): - '''Dump the console log buffer contents found at address base.''' - - class ConsoleHeader(CStruct): - struct_members = ( - ("L", "size"), - ("L", "cursor") - ) - - header = ConsoleHeader(base) - print 'cursor at %d\n' % header.cursor - - cons_addr = base + header.struct_len - cons_length = min(header.cursor, header.size) - cons_text = get_phys_mem(cons_addr, cons_length) - print cons_text - print '\n' - -def ipchksum(buf): - '''Checksumming function used on the coreboot tables. The buffer being - checksummed is summed up as if it was an array of 16 bit unsigned - integers. If there are an odd number of bytes, the last element is zero - extended.''' - - size = len(buf) - odd = size % 2 - fmt = "<%dH" % ((size - odd) / 2) - if odd: - fmt += "B" - shorts = struct.unpack(fmt, buf) - checksum = sum(shorts) - checksum = (checksum >> 16) + (checksum & 0xffff) - checksum += (checksum >> 16) - checksum = ~checksum & 0xffff - return checksum - -def parse_tables(base, length): - '''Find the coreboot tables in memory and process whatever we can.''' - - class CBTableHeader(CStruct): - struct_members = ( - ("4s", "signature"), - ("I", "header_bytes"), - ("I", "header_checksum"), - ("I", "table_bytes"), - ("I", "table_checksum"), - ("I", "table_entries") - ) - - class CBTableEntry(CStruct): - struct_members = ( - ("I", "tag"), - ("I", "size") - ) - - class CBTableForward(CBTableEntry): - struct_members = CBTableEntry.struct_members + ( - ("Q", "forward"), - ) - - class CBMemTab(CBTableEntry): - struct_members = CBTableEntry.struct_members + ( - ("L", "cbmem_tab"), - ) - - for addr in range(base, base + length, 16): - header = CBTableHeader(addr) - if header.signature == "LBIO": - break - else: - return -1 - - if header.header_bytes == 0: - return -1 - - if ipchksum(header.raw_memory) != 0: - print "Bad header checksum" - return -1 - - addr += header.header_bytes - table = get_phys_mem(addr, header.table_bytes) - if ipchksum(table) != header.table_checksum: - print "Bad table checksum" - return -1 - - for i in range(header.table_entries): - entry = CBTableEntry(addr) - if entry.tag == 0x11: # Forwarding entry - return parse_tables(CBTableForward(addr).forward, length) - elif entry.tag == 0x16: # Timestamps - process_timers(CBMemTab(addr).cbmem_tab) - elif entry.tag == 0x17: # CBMEM console - process_console(CBMemTab(addr).cbmem_tab) - - addr += entry.size - - return 0 - -def main(): - for base, length in (0x00000000, 0x1000), (0x000f0000, 0x1000): - if parse_tables(base, length): - break - else: - print "Didn't find the coreboot tables" - return 0 - -if __name__ == "__main__": - sys.exit(main()) From gerrit at coreboot.org Mon Jan 7 23:46:37 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Mon, 7 Jan 2013 23:46:37 +0100 Subject: [coreboot] Patch set updated for coreboot: d64a48e cbmem utility: drop obsolete python based implementation References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2115 -gerrit commit d64a48e7cb188200d124b11f53d47681489f91b8 Author: Stefan Reinauer Date: Mon Jan 7 13:39:43 2013 -0800 cbmem utility: drop obsolete python based implementation The first version of the cbmem utility was written in python, but it had issues with 64bit systems and other little hick ups. Since the C version has much fewer dependencies (no python needed on target system), and it works in all corner cases, drop the python version. Change-Id: Ida3d6c9bb46f6d826f45538e4ceaa4fc1e771ff5 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.py | 259 ---------------------------------------------------- 1 file changed, 259 deletions(-) diff --git a/util/cbmem/cbmem.py b/util/cbmem/cbmem.py deleted file mode 100755 index 70ccc00..0000000 --- a/util/cbmem/cbmem.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/python -# -# cbmem.py - Linux space CBMEM contents parser -# -# Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -''' -Parse and display CBMEM contents. - -This module is meant to run on systems with coreboot based firmware. - -When started, it determines the amount of DRAM installed on the system, and -then scans the top area of DRAM (right above the available memory size) -looking for the CBMEM base signature at locations aligned at 0x20000 -boundaries. - -Once it finds the CBMEM signature, the utility parses the contents, reporting -the section IDs/sizes and also reporting the contents of the tiemstamp and -console sections. -''' - -import mmap -import struct -import sys - -def get_phys_mem(addr, size): - '''Read size bytes from address addr by mmaping /dev/mem''' - - mf = open("/dev/mem") - delta = addr % 4096 - mm = mmap.mmap(mf.fileno(), size + delta, - mmap.MAP_PRIVATE, offset=(addr - delta)) - buf = mm.read(size + delta) - mf.close() - return buf[delta:] - -# This class and metaclass make it easier to define and access structures -# which live in physical memory. To use them, inherit from CStruct and define -# a class member called struct_members which is a tuple of pairs. The first -# item in the pair is the type format specifier that should be used with -# struct.unpack to read that member from memory. The second item is the name -# that member should have in the resulting object. - -class MetaCStruct(type): - def __init__(cls, name, bases, dct): - struct_members = dct["struct_members"] - cls.struct_fmt = "<" - for char, name in struct_members: - cls.struct_fmt += char - cls.struct_len = struct.calcsize(cls.struct_fmt) - super(MetaCStruct, cls).__init__(name, bases, dct) - -class CStruct(object): - __metaclass__ = MetaCStruct - struct_members = () - - def __init__(self, addr): - self.raw_memory = get_phys_mem(addr, self.struct_len) - values = struct.unpack(self.struct_fmt, self.raw_memory) - names = (name for char, name in self.struct_members) - for name, value in zip(names, values): - setattr(self, name, value) - -def normalize_timer(value, freq): - '''Convert timer reading into microseconds. - - Get the free running clock counter value, divide it by the clock frequency - and multiply by 1 million to get reading in microseconds. - - Then convert the value into an ASCII string with groups of three digits - separated by commas. - - Inputs: - value: int, the clock reading - freq: float, the clock frequency - - Returns: - A string presenting 'value' in microseconds. - ''' - - result = [] - value = int(value * 1000000.0 / freq) - svalue = '%d' % value - vlength = len(svalue) - remainder = vlength % 3 - if remainder: - result.append(svalue[0:remainder]) - while remainder < vlength: - result.append(svalue[remainder:remainder+3]) - remainder = remainder + 3 - return ','.join(result) - -def get_cpu_freq(): - '''Retrieve CPU frequency from sysfs. - - Use /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq as the source. - ''' - freq_str = open('/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq' - ).read() - # Convert reading into Hertz - return float(freq_str) * 1000.0 - -def process_timers(base): - '''Scan the array of timestamps found in CBMEM at address base. - - For each timestamp print the timer ID and the value in microseconds. - ''' - - class TimestampHeader(CStruct): - struct_members = ( - ("Q", "base_time"), - ("L", "max_entr"), - ("L", "entr") - ) - - class TimestampEntry(CStruct): - struct_members = ( - ("L", "timer_id"), - ("Q", "timer_value") - ) - - header = TimestampHeader(base) - print('\ntime base %d, total entries %d' % (header.base_time, header.entr)) - clock_freq = get_cpu_freq() - base = base + header.struct_len - prev_time = 0 - for i in range(header.entr): - timestamp = TimestampEntry(base) - print '%d:%s ' % (timestamp.timer_id, - normalize_timer(timestamp.timer_value, clock_freq)), - if prev_time: - print '(%s)' % normalize_timer( - timestamp.timer_value - prev_time, clock_freq), - prev_time = timestamp.timer_value - print - base = base + timestamp.struct_len - print - -def process_console(base): - '''Dump the console log buffer contents found at address base.''' - - class ConsoleHeader(CStruct): - struct_members = ( - ("L", "size"), - ("L", "cursor") - ) - - header = ConsoleHeader(base) - print 'cursor at %d\n' % header.cursor - - cons_addr = base + header.struct_len - cons_length = min(header.cursor, header.size) - cons_text = get_phys_mem(cons_addr, cons_length) - print cons_text - print '\n' - -def ipchksum(buf): - '''Checksumming function used on the coreboot tables. The buffer being - checksummed is summed up as if it was an array of 16 bit unsigned - integers. If there are an odd number of bytes, the last element is zero - extended.''' - - size = len(buf) - odd = size % 2 - fmt = "<%dH" % ((size - odd) / 2) - if odd: - fmt += "B" - shorts = struct.unpack(fmt, buf) - checksum = sum(shorts) - checksum = (checksum >> 16) + (checksum & 0xffff) - checksum += (checksum >> 16) - checksum = ~checksum & 0xffff - return checksum - -def parse_tables(base, length): - '''Find the coreboot tables in memory and process whatever we can.''' - - class CBTableHeader(CStruct): - struct_members = ( - ("4s", "signature"), - ("I", "header_bytes"), - ("I", "header_checksum"), - ("I", "table_bytes"), - ("I", "table_checksum"), - ("I", "table_entries") - ) - - class CBTableEntry(CStruct): - struct_members = ( - ("I", "tag"), - ("I", "size") - ) - - class CBTableForward(CBTableEntry): - struct_members = CBTableEntry.struct_members + ( - ("Q", "forward"), - ) - - class CBMemTab(CBTableEntry): - struct_members = CBTableEntry.struct_members + ( - ("L", "cbmem_tab"), - ) - - for addr in range(base, base + length, 16): - header = CBTableHeader(addr) - if header.signature == "LBIO": - break - else: - return -1 - - if header.header_bytes == 0: - return -1 - - if ipchksum(header.raw_memory) != 0: - print "Bad header checksum" - return -1 - - addr += header.header_bytes - table = get_phys_mem(addr, header.table_bytes) - if ipchksum(table) != header.table_checksum: - print "Bad table checksum" - return -1 - - for i in range(header.table_entries): - entry = CBTableEntry(addr) - if entry.tag == 0x11: # Forwarding entry - return parse_tables(CBTableForward(addr).forward, length) - elif entry.tag == 0x16: # Timestamps - process_timers(CBMemTab(addr).cbmem_tab) - elif entry.tag == 0x17: # CBMEM console - process_console(CBMemTab(addr).cbmem_tab) - - addr += entry.size - - return 0 - -def main(): - for base, length in (0x00000000, 0x1000), (0x000f0000, 0x1000): - if parse_tables(base, length): - break - else: - print "Didn't find the coreboot tables" - return 0 - -if __name__ == "__main__": - sys.exit(main()) From gerrit at coreboot.org Tue Jan 8 00:04:34 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Tue, 8 Jan 2013 00:04:34 +0100 Subject: [coreboot] Patch merged into coreboot/master: 1665bb3 cbmem utility: drop obsolete python based implementation References: Message-ID: the following patch was just integrated into master: commit 1665bb3896e49f84a28e24176734f447f3a0899b Author: Stefan Reinauer Date: Mon Jan 7 13:39:43 2013 -0800 cbmem utility: drop obsolete python based implementation The first version of the cbmem utility was written in python, but it had issues with 64bit systems and other little hick ups. Since the C version has much fewer dependencies (no python needed on target system), and it works in all corner cases, drop the python version. Change-Id: Ida3d6c9bb46f6d826f45538e4ceaa4fc1e771ff5 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2115 Reviewed-by: Vadim Bendebury Tested-by: build bot (Jenkins) Build-Tested: build bot (Jenkins) at Mon Jan 7 23:53:31 2013, giving +1 See http://review.coreboot.org/2115 for details. -gerrit From gerrit at coreboot.org Tue Jan 8 00:22:25 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 00:22:25 +0100 Subject: [coreboot] Patch set updated for coreboot: 8112407 cbmem utility: Add option to dump cbmem console References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2114 -gerrit commit 81124070b8cac3a33411e4f0809976fa7f213f57 Author: Stefan Reinauer Date: Mon Jan 7 13:37:12 2013 -0800 cbmem utility: Add option to dump cbmem console This adds an option to the cbmem utility to dump the cbmem console. To keep the utility backwards compatible, specifying -c disables printing of time stamps. To print both console and time stamps, run the utility with -ct Change-Id: Idd2dbf32c3c44f857c2f41e6c817c5ab13155d6f Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index df00684..bcbc9ce 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -283,6 +283,41 @@ static void dump_timestamps(void) unmap_memory(); } +/* dump the cbmem console */ +static void dump_console(void) +{ + void *console_p; + char *console_c; + uint32_t size; + + if (console.tag != LB_TAG_CBMEM_CONSOLE) { + fprintf(stderr, "No console found in coreboot table.\n"); + return; + } + + console_p = map_memory((unsigned long)console.cbmem_addr); + /* The in-memory format of the console area is: + * u32 size + * u32 cursor + * char console[size] + * Hence we have to add 8 to get to the actual console string. + */ + size = *(uint32_t *)console_p; + console_c = malloc(size + 1); + if (!console_c) { + fprintf(stderr, "Not enough memory for console.\n"); + exit(1); + } + + memcpy(console_c, console_p + 8, size); + console_c[size] = 0; + + printf("%s", console_c); + + unmap_memory(); +} + + void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); @@ -303,6 +338,9 @@ void print_usage(const char *name) { printf("usage: %s [-vh?]\n", name); printf("\n" + " -c | --console: print cbmem console\n" + " -t | --timestamps: print timestamp information\n" + " -V | --verbose: verbose (debugging) output\n" " -v | --version: print the version\n" " -h | --help: print this help\n" "\n"); @@ -314,18 +352,30 @@ int main(int argc, char** argv) int j; static const int possible_base_addresses[] = { 0, 0xf0000 }; - int print_timestamps = 1; + int print_defaults = 1; + int print_console = 0; + int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { + {"console", 0, 0, 'c'}, + {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "Vvh?", + while ((opt = getopt_long(argc, argv, "ctVvh?", long_options, &option_index)) != EOF) { switch (opt) { + case 'c': + print_console = 1; + print_defaults = 0; + break; + case 't': + print_timestamps = 1; + print_defaults = 0; + break; case 'V': verbose = 1; break; @@ -355,7 +405,10 @@ int main(int argc, char** argv) break; } - if (print_timestamps) + if (print_console) + dump_console(); + + if (print_defaults || print_timestamps) dump_timestamps(); close(fd); From gerrit at coreboot.org Tue Jan 8 00:23:38 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 00:23:38 +0100 Subject: [coreboot] Patch set updated for coreboot: bd7fa41 cbmem utility: Add option to dump cbmem console References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2114 -gerrit commit bd7fa41828941d78e4edfacb13a4132d731552ce Author: Stefan Reinauer Date: Mon Jan 7 13:37:12 2013 -0800 cbmem utility: Add option to dump cbmem console This adds an option to the cbmem utility to dump the cbmem console. To keep the utility backwards compatible, specifying -c disables printing of time stamps. To print both console and time stamps, run the utility with -ct Change-Id: Idd2dbf32c3c44f857c2f41e6c817c5ab13155d6f Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index df00684..4c0bd68 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -283,6 +283,43 @@ static void dump_timestamps(void) unmap_memory(); } +/* dump the cbmem console */ +static void dump_console(void) +{ + void *console_p; + char *console_c; + uint32_t size; + + if (console.tag != LB_TAG_CBMEM_CONSOLE) { + fprintf(stderr, "No console found in coreboot table.\n"); + return; + } + + console_p = map_memory((unsigned long)console.cbmem_addr); + /* The in-memory format of the console area is: + * u32 size + * u32 cursor + * char console[size] + * Hence we have to add 8 to get to the actual console string. + */ + size = *(uint32_t *)console_p; + console_c = malloc(size + 1); + if (!console_c) { + fprintf(stderr, "Not enough memory for console.\n"); + exit(1); + } + + memcpy(console_c, console_p + 8, size); + console_c[size] = 0; + + printf("%s", console_c); + + free(console_c); + + unmap_memory(); +} + + void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); @@ -303,6 +340,9 @@ void print_usage(const char *name) { printf("usage: %s [-vh?]\n", name); printf("\n" + " -c | --console: print cbmem console\n" + " -t | --timestamps: print timestamp information\n" + " -V | --verbose: verbose (debugging) output\n" " -v | --version: print the version\n" " -h | --help: print this help\n" "\n"); @@ -314,18 +354,30 @@ int main(int argc, char** argv) int j; static const int possible_base_addresses[] = { 0, 0xf0000 }; - int print_timestamps = 1; + int print_defaults = 1; + int print_console = 0; + int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { + {"console", 0, 0, 'c'}, + {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "Vvh?", + while ((opt = getopt_long(argc, argv, "ctVvh?", long_options, &option_index)) != EOF) { switch (opt) { + case 'c': + print_console = 1; + print_defaults = 0; + break; + case 't': + print_timestamps = 1; + print_defaults = 0; + break; case 'V': verbose = 1; break; @@ -355,7 +407,10 @@ int main(int argc, char** argv) break; } - if (print_timestamps) + if (print_console) + dump_console(); + + if (print_defaults || print_timestamps) dump_timestamps(); close(fd); From gerrit at coreboot.org Tue Jan 8 00:26:22 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 00:26:22 +0100 Subject: [coreboot] New patch to review for coreboot: d027fbc cbmem utility: unify debug output References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2116 -gerrit commit d027fbc3cbf4c32d8e1dd13ab22632dd5b7dbab8 Author: Stefan Reinauer Date: Mon Jan 7 15:25:37 2013 -0800 cbmem utility: unify debug output ... and indent it to make output more comprehensible. Change-Id: If321f3233b31be14b2723175b781e5dd60dd72b6 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 4c0bd68..59d0540 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -158,12 +158,12 @@ static int parse_cbtable(u64 address) debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { case LB_TAG_TIMESTAMPS: { - debug("Found timestamp table\n"); + debug(" Found timestamp table.\n"); timestamps = *(struct lb_cbmem_ref *) lbr_p; continue; } case LB_TAG_CBMEM_CONSOLE: { - debug("Found cbmem console\n"); + debug(" Found cbmem console.\n"); console = *(struct lb_cbmem_ref *) lbr_p; continue; } @@ -174,6 +174,7 @@ static int parse_cbtable(u64 address) */ struct lb_forward lbf_p = *(struct lb_forward *) lbr_p; + debug(" Found forwarding entry.\n"); unmap_memory(); return parse_cbtable(lbf_p.forward); } From gerrit at coreboot.org Tue Jan 8 01:24:11 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Tue, 8 Jan 2013 01:24:11 +0100 Subject: [coreboot] Patch merged into coreboot/master: 19f8756 cbmem utility: Add option to dump cbmem console References: Message-ID: the following patch was just integrated into master: commit 19f8756f0008cf74a472177642cc44f00c05934f Author: Stefan Reinauer Date: Mon Jan 7 13:37:12 2013 -0800 cbmem utility: Add option to dump cbmem console This adds an option to the cbmem utility to dump the cbmem console. To keep the utility backwards compatible, specifying -c disables printing of time stamps. To print both console and time stamps, run the utility with -ct Change-Id: Idd2dbf32c3c44f857c2f41e6c817c5ab13155d6f Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2114 Tested-by: build bot (Jenkins) Reviewed-by: Vadim Bendebury Build-Tested: build bot (Jenkins) at Tue Jan 8 00:35:41 2013, giving +1 See http://review.coreboot.org/2114 for details. -gerrit From gerrit at coreboot.org Tue Jan 8 01:28:36 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 01:28:36 +0100 Subject: [coreboot] New patch to review for coreboot: da023a4 cbmem utility: Find actual CBMEM area References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2117 -gerrit commit da023a4f3c6a5bc89b1b0590fb8a28c4c67c0dbc Author: Stefan Reinauer Date: Mon Jan 7 16:26:10 2013 -0800 cbmem utility: Find actual CBMEM area without the need for a coreboot table entry for each of them. WIP. This will be used to extract code coverage data Change-Id: I2917710fb9d00c4533d81331a362bf0c40a30353 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 4c0bd68..269a29c 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -118,6 +118,7 @@ static void unmap_memory(void) static struct lb_cbmem_ref timestamps; static struct lb_cbmem_ref console; +static struct lb_memory_range cbmem; static int parse_cbtable(u64 address) { @@ -157,6 +158,22 @@ static int parse_cbtable(u64 address) lbr_p = (struct lb_record*) ((char *)lbtable + j); debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { + case LB_TAG_MEMORY: { + int i = 0; + debug(" Found memory map.\n"); + struct lb_memory *memory = + (struct lb_memory *)lbr_p; + while ((char *)&memory->map[i] < ((char *)lbtable + + lbr_p->size)) { + if (memory->map[i].type == LB_MEM_TABLE) { + debug(" LB_MEM_TABLE found.\n"); + /* The last one found is CBMEM */ + cbmem = memory->map[i]; + } + i++; + } + continue; + } case LB_TAG_TIMESTAMPS: { debug("Found timestamp table\n"); timestamps = *(struct lb_cbmem_ref *) lbr_p; @@ -319,6 +336,39 @@ static void dump_console(void) unmap_memory(); } +#define CBMEM_MAGIC 0x434f5245 +#define MAX_CBMEM_ENTRIES 16 + +struct cbmem_entry { + uint32_t magic; + uint32_t id; + uint64_t base; + uint64_t size; +}; + +void dump_cbmem_toc(void) +{ + int i; + uint64_t start; + struct cbmem_entry *entries; + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + for (i=0; i Message-ID: Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2112 -gerrit commit 8fa685b1b18b12c6c672488a76f42dfda1604917 Author: zbao Date: Tue Jan 8 10:10:16 2013 +0800 cbfstool: index is replaced by strchr. From index(3): CONFORMING TO 4.3BSD; marked as LEGACY in POSIX.1-2001. POSIX.1-2008 removes the specifications of index() and rindex(), recommending strchr(3) and strrchr(3) instead. Change-Id: I3899b9ca9196dbbf2d147a38dacd7e742a3873fe Signed-off-by: Zheng Bao Signed-off-by: zbao --- util/cbfstool/cbfstool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 6b52062..4202801 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -563,7 +563,7 @@ int main(int argc, char **argv) break; /* filter out illegal long options */ - if (index(commands[i].optstring, c) == NULL) { + if (strchr(commands[i].optstring, c) == NULL) { /* TODO maybe print actual long option instead */ printf("%s: invalid option -- '%c'\n", argv[0], c); From gerrit at coreboot.org Tue Jan 8 03:13:40 2013 From: gerrit at coreboot.org (Zheng Bao (zheng.bao@amd.com)) Date: Tue, 8 Jan 2013 03:13:40 +0100 Subject: [coreboot] Patch set updated for coreboot: 887f3b9 cbfstool: index is replaced by strchr. References: Message-ID: Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2112 -gerrit commit 887f3b9899c9bfb4ab8dd3ca1d5bf06815e2c212 Author: zbao Date: Tue Jan 8 10:10:16 2013 +0800 cbfstool: index is replaced by strchr. From index(3): CONFORMING TO 4.3BSD; marked as LEGACY in POSIX.1-2001. POSIX.1-2008 removes the specifications of index() and rindex(), recommending strchr(3) and strrchr(3) instead. Change-Id: I3899b9ca9196dbbf2d147a38dacd7e742a3873fe Signed-off-by: Zheng Bao Signed-off-by: zbao --- util/cbfstool/cbfstool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 6b52062..4202801 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -563,7 +563,7 @@ int main(int argc, char **argv) break; /* filter out illegal long options */ - if (index(commands[i].optstring, c) == NULL) { + if (strchr(commands[i].optstring, c) == NULL) { /* TODO maybe print actual long option instead */ printf("%s: invalid option -- '%c'\n", argv[0], c); From gerrit at coreboot.org Tue Jan 8 04:00:31 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Tue, 8 Jan 2013 04:00:31 +0100 Subject: [coreboot] Patch merged into coreboot/master: 062730d cbfstool: index is replaced by strchr. References: Message-ID: the following patch was just integrated into master: commit 062730d7cb35c8cc2cc07e15695eb62f2b647f4a Author: zbao Date: Tue Jan 8 10:10:16 2013 +0800 cbfstool: index is replaced by strchr. From index(3): CONFORMING TO 4.3BSD; marked as LEGACY in POSIX.1-2001. POSIX.1-2008 removes the specifications of index() and rindex(), recommending strchr(3) and strrchr(3) instead. Change-Id: I3899b9ca9196dbbf2d147a38dacd7e742a3873fe Signed-off-by: Zheng Bao Signed-off-by: zbao Reviewed-on: http://review.coreboot.org/2112 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer Build-Tested: build bot (Jenkins) at Tue Jan 8 03:23:37 2013, giving +1 Reviewed-By: Stefan Reinauer at Tue Jan 8 04:00:30 2013, giving +2 See http://review.coreboot.org/2112 for details. -gerrit From maciej.grela at gmail.com Tue Jan 8 00:26:56 2013 From: maciej.grela at gmail.com (Maciej Grela) Date: Mon, 7 Jan 2013 23:26:56 +0000 Subject: [coreboot] Adding support for Kobian 815ep FSX mobo (82815 + 82801BA + IT8712F) - is it a good first time coreboot project? Message-ID: Hi, I've been watching the developments of LinuxBIOS and coreboot projects for some time now and I wanted to get involved in coreboot because I think it's a cool project. I think, that trying to make my old simple mobo to work with coreboot would be a good first time task. All of the chips are supported as far as I can see on the webpage but looking at the status of 82815 I would have to port it to from v1 to v4, right? I have some embedded experience (microcontrollers) but no knowledge of coreboot code. Is porting northbridge support hard? Thanks for your answers. -- Maciej Grela From rminnich at gmail.com Tue Jan 8 05:36:53 2013 From: rminnich at gmail.com (ron minnich) Date: Mon, 7 Jan 2013 20:36:53 -0800 Subject: [coreboot] Adding support for Kobian 815ep FSX mobo (82815 + 82801BA + IT8712F) - is it a good first time coreboot project? In-Reply-To: References: Message-ID: The best first-time project is to take a board that is known to work and do all the work of making it work. Sounds simple, never is. Then move on to a new board! thanks ron From GNUtoo at no-log.org Tue Jan 8 19:42:29 2013 From: GNUtoo at no-log.org (Denis 'GNUtoo' Carikli) Date: Tue, 8 Jan 2013 19:42:29 +0100 Subject: [coreboot] FOSDEM 2013 - who else comes? In-Reply-To: <50E4AA1E.8030508@assembler.cz> References: <50E4AA1E.8030508@assembler.cz> Message-ID: <20130108194229.504fd301@no-log.org> On Wed, 02 Jan 2013 22:43:58 +0100 Rudolf Marek wrote: > Hi all, > > As Carl-Daniel wrote we have a stand (two tables) at FOSDEM on 2,3rd > February in Brussel. > > So far me and Carl-Daniel will come. I will arrive early on Friday > and leave on Sunday evening. I will bring my boards with me (2?) and > of course also F2A85-M. > > If anyone wants to come, please let us know. > > Thanks > Rudolf I'll come too, altough I can't bring my M4a785T-M(too big). I'll probably bring my x60 tough but I guess that many people already have an x60. Denis. From gerrit at coreboot.org Tue Jan 8 20:20:43 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 20:20:43 +0100 Subject: [coreboot] Patch set updated for coreboot: 47f24e8 cbmem utility: Find actual CBMEM area References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2117 -gerrit commit 47f24e8b47fe7521650f5766451b28354828fa63 Author: Stefan Reinauer Date: Mon Jan 7 16:26:10 2013 -0800 cbmem utility: Find actual CBMEM area ... without the need for a coreboot table entry for each of them. Change-Id: I2917710fb9d00c4533d81331a362bf0c40a30353 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 4c0bd68..4d1a7b5 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -118,6 +118,7 @@ static void unmap_memory(void) static struct lb_cbmem_ref timestamps; static struct lb_cbmem_ref console; +static struct lb_memory_range cbmem; static int parse_cbtable(u64 address) { @@ -157,6 +158,22 @@ static int parse_cbtable(u64 address) lbr_p = (struct lb_record*) ((char *)lbtable + j); debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { + case LB_TAG_MEMORY: { + int i = 0; + debug(" Found memory map.\n"); + struct lb_memory *memory = + (struct lb_memory *)lbr_p; + while ((char *)&memory->map[i] < ((char *)lbtable + + lbr_p->size)) { + if (memory->map[i].type == LB_MEM_TABLE) { + debug(" LB_MEM_TABLE found.\n"); + /* The last one found is CBMEM */ + cbmem = memory->map[i]; + } + i++; + } + continue; + } case LB_TAG_TIMESTAMPS: { debug("Found timestamp table\n"); timestamps = *(struct lb_cbmem_ref *) lbr_p; @@ -319,6 +336,61 @@ static void dump_console(void) unmap_memory(); } +#define CBMEM_MAGIC 0x434f5245 +#define MAX_CBMEM_ENTRIES 16 + +struct cbmem_entry { + uint32_t magic; + uint32_t id; + uint64_t base; + uint64_t size; +}; + +void dump_cbmem_toc(void) +{ + int i; + uint64_t start; + struct cbmem_entry *entries; + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + printf("CBMEM table of contents:\n"); + printf(" ID START LENGTH\n"); + for (i=0; i Message-ID: the following patch was just integrated into master: commit d7144dcd578215e345b10df5a6cdac7bd44ac3ad Author: Stefan Reinauer Date: Mon Jan 7 15:25:37 2013 -0800 cbmem utility: unify debug output ... and indent it to make output more comprehensible. Change-Id: If321f3233b31be14b2723175b781e5dd60dd72b6 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2116 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Tue Jan 8 00:42:11 2013, giving +1 Reviewed-By: Ronald G. Minnich at Tue Jan 8 20:25:21 2013, giving +2 See http://review.coreboot.org/2116 for details. -gerrit From gerrit at coreboot.org Tue Jan 8 20:30:46 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Tue, 8 Jan 2013 20:30:46 +0100 Subject: [coreboot] Patch set updated for coreboot: 9a0ead9 cbmem utility: Find actual CBMEM area References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2117 -gerrit commit 9a0ead9ca09771be2dd00817157e6212c5a7f90e Author: Stefan Reinauer Date: Mon Jan 7 16:26:10 2013 -0800 cbmem utility: Find actual CBMEM area ... without the need for a coreboot table entry for each of them. Change-Id: I2917710fb9d00c4533d81331a362bf0c40a30353 Signed-off-by: Stefan Reinauer --- util/cbmem/cbmem.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 4c0bd68..8758187 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -118,6 +118,7 @@ static void unmap_memory(void) static struct lb_cbmem_ref timestamps; static struct lb_cbmem_ref console; +static struct lb_memory_range cbmem; static int parse_cbtable(u64 address) { @@ -157,6 +158,22 @@ static int parse_cbtable(u64 address) lbr_p = (struct lb_record*) ((char *)lbtable + j); debug(" coreboot table entry 0x%02x\n", lbr_p->tag); switch (lbr_p->tag) { + case LB_TAG_MEMORY: { + int i = 0; + debug(" Found memory map.\n"); + struct lb_memory *memory = + (struct lb_memory *)lbr_p; + while ((char *)&memory->map[i] < ((char *)lbtable + + lbr_p->size)) { + if (memory->map[i].type == LB_MEM_TABLE) { + debug(" LB_MEM_TABLE found.\n"); + /* The last one found is CBMEM */ + cbmem = memory->map[i]; + } + i++; + } + continue; + } case LB_TAG_TIMESTAMPS: { debug("Found timestamp table\n"); timestamps = *(struct lb_cbmem_ref *) lbr_p; @@ -319,6 +336,61 @@ static void dump_console(void) unmap_memory(); } +#define CBMEM_MAGIC 0x434f5245 +#define MAX_CBMEM_ENTRIES 16 + +struct cbmem_entry { + uint32_t magic; + uint32_t id; + uint64_t base; + uint64_t size; +}; + +void dump_cbmem_toc(void) +{ + int i; + uint64_t start; + struct cbmem_entry *entries; + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + printf("CBMEM table of contents:\n"); + printf(" ID START LENGTH\n"); + for (i=0; i Message-ID: the following patch was just integrated into master: commit c01990789f533316e10c5fc3b5ca08ae866b8033 Author: Stefan Reinauer Date: Mon Jan 7 16:26:10 2013 -0800 cbmem utility: Find actual CBMEM area ... without the need for a coreboot table entry for each of them. Change-Id: I2917710fb9d00c4533d81331a362bf0c40a30353 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2117 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Tue Jan 8 20:37:30 2013, giving +1 Reviewed-By: Ronald G. Minnich at Tue Jan 8 20:40:26 2013, giving +2 See http://review.coreboot.org/2117 for details. -gerrit From c-d.hailfinger.devel.2006 at gmx.net Tue Jan 8 22:50:40 2013 From: c-d.hailfinger.devel.2006 at gmx.net (Carl-Daniel Hailfinger) Date: Tue, 08 Jan 2013 22:50:40 +0100 Subject: [coreboot] FOSDEM 2013 - who else comes? In-Reply-To: <20130108194229.504fd301@no-log.org> References: <50E4AA1E.8030508@assembler.cz> <20130108194229.504fd301@no-log.org> Message-ID: <50EC94B0.6080306@gmx.net> Am 08.01.2013 19:42 schrieb Denis 'GNUtoo' Carikli: > On Wed, 02 Jan 2013 22:43:58 +0100 > Rudolf Marek wrote: > >> Hi all, >> >> As Carl-Daniel wrote we have a stand (two tables) at FOSDEM on 2,3rd >> February in Brussel. >> >> So far me and Carl-Daniel will come. I will arrive early on Friday >> and leave on Sunday evening. I will bring my boards with me (2?) and >> of course also F2A85-M. >> > I'll come too, altough I can't bring my M4a785T-M(too big). > I'll probably bring my x60 tough but I guess that many people already > have an x60. Please bring it along, I don't have a coreboot laptop (long story). Regards, Carl-Daniel -- http://www.hailfinger.org/ From gerrit at coreboot.org Tue Jan 8 23:33:36 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Tue, 8 Jan 2013 23:33:36 +0100 Subject: [coreboot] Patch merged into coreboot/master: 597ff87 qemu-x86: Implement more features References: Message-ID: the following patch was just integrated into master: commit 597ff87574b11dc1163eb152e0941a2cbce5341b Author: Stefan Reinauer Date: Mon Jan 7 13:21:22 2013 -0800 qemu-x86: Implement more features This patch switches the Qemu target to use (pseudo) Cache As RAM and enables some ACPI code. This allows to use the CBMEM console and timestamp code with coreboot in Qemu. Right now, the ACPI code is commented out because leaving it in breaks IDE. Change-Id: Ie20f3ecc194004f354ae3437b9cf9175382cadf8 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/2113 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich Build-Tested: build bot (Jenkins) at Mon Jan 7 22:32:00 2013, giving +1 Reviewed-By: Ronald G. Minnich at Tue Jan 8 23:33:35 2013, giving +2 See http://review.coreboot.org/2113 for details. -gerrit From gerrit at coreboot.org Wed Jan 9 00:15:51 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Wed, 9 Jan 2013 00:15:51 +0100 Subject: [coreboot] Patch set updated for coreboot: 38d0e93 Implement GCC code coverage analysis References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2052 -gerrit commit 38d0e936c51caba080d15b9a3725264dbed62c1c Author: Stefan Reinauer Date: Tue Dec 18 16:23:28 2012 -0800 Implement GCC code coverage analysis In order to provide some insight on what code is executed during coreboot's run time and how well our test scenarios work, this adds code coverage support to coreboot's ram stage. This should be easily adaptable for payloads, and maybe even romstage. See http://gcc.gnu.org/onlinedocs/gcc/Gcov.html for more information. To instrument coreboot, select CONFIG_COVERAGE ("Code coverage support") in Kconfig, and recompile coreboot. coreboot will then store its code coverage information into CBMEM, if possible. Then, run "cbmem -CV" as root on the target system running the instrumented coreboot binary. This will create a whole bunch of .gcda files that contain coverage information. Tar them up, copy them to your build system machine, and untar them. Then you can use your favorite coverage utility (gcov, lcov, ...) to visualize code coverage. There is no example run for coreboot's coverage yet. However, for a sneak peak of what will expect you, please take a look at OpenBIOS' fcode suite's coverage report: http://www.openfirmware.info/data/coverage-fcode-suite-1.0.2/ Change-Id: Ib287d8309878a1f5c4be770c38b1bc0bb3aa6ec7 Signed-off-by: Stefan Reinauer --- Makefile.inc | 3 + src/Kconfig | 18 + src/arch/armv7/coreboot_ram.ld | 8 + src/arch/x86/Makefile.inc | 2 +- src/arch/x86/boot/acpi.c | 4 + src/arch/x86/coreboot_ram.ld | 8 + src/include/cbmem.h | 1 + src/include/coverage.h | 21 + src/lib/Makefile.inc | 1 + src/lib/cbmem.c | 2 + src/lib/gcov-glue.c | 153 ++++++ src/lib/gcov-io.c | 556 +++++++++++++++++++ src/lib/gcov-io.h | 639 ++++++++++++++++++++++ src/lib/gcov-iov.h | 4 + src/lib/hardwaremain.c | 5 + src/lib/libgcov.c | 1158 ++++++++++++++++++++++++++++++++++++++++ src/lib/selfboot.c | 4 + util/cbmem/cbmem.c | 136 ++++- 18 files changed, 2715 insertions(+), 8 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index a066e25..3731797 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,6 +99,9 @@ romstage-S-ccopts:=-D__PRE_RAM__ ifeq ($(CONFIG_TRACE),y) ramstage-c-ccopts:= -finstrument-functions endif +ifeq ($(CONFIG_COVERAGE),y) +ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) diff --git a/src/Kconfig b/src/Kconfig index 0a94ed8..2c97327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,15 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail. +config COVERAGE + bool "Code coverage support" + depends on COMPILER_GCC + default n + help + Add code coverage support for coreboot. This will store code + coverage information in CBMEM for extraction from user space. + If unsure, say N. + endmenu source src/mainboard/Kconfig @@ -868,6 +877,15 @@ config TRACE the 0xaaaabbbb is the actual function and 0xccccdddd is EIP of calling function. Please note some printk releated functions are omitted from trace to have good looking console dumps. + +config DEBUG_COVERAGE + bool "Debug code coverage" + default n + depends on COVERAGE + help + If enabled, the code coverage hooks in coreboot will output some + information about the coverage data that is dumped. + endmenu # These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/armv7/coreboot_ram.ld b/src/arch/armv7/coreboot_ram.ld index 57ddd03..329bce4 100644 --- a/src/arch/armv7/coreboot_ram.ld +++ b/src/arch/armv7/coreboot_ram.ld @@ -38,6 +38,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index e84700e..ea86f8f 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -166,7 +166,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 1d7dbf8..730e53e 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -36,6 +36,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -642,6 +643,9 @@ void suspend_resume(void) /* Call mainboard resume handler first, if defined. */ if (mainboard_suspend_resume) mainboard_suspend_resume(); +#if CONFIG_COVERAGE + coverage_exit(); +#endif post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); } diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld index a87a0e7..7ce0367 100644 --- a/src/arch/x86/coreboot_ram.ld +++ b/src/arch/x86/coreboot_ram.ld @@ -39,6 +39,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 21efe77..08e913a 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -55,6 +55,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_COVERAGE 0x47434f56 #define CBMEM_ID_NONE 0x00000000 #ifndef __ASSEMBLER__ diff --git a/src/include/coverage.h b/src/include/coverage.h new file mode 100644 index 0000000..e1c50c5 --- /dev/null +++ b/src/include/coverage.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void coverage_init(void); +void coverage_exit(void); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6b3f0d8..6796448 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -70,6 +70,7 @@ ramstage-$(CONFIG_USBDEBUG) += usbdebug.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index 7378d8c..f270f5d 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -260,6 +260,8 @@ void cbmem_list(void) case CBMEM_ID_TIMESTAMP: printk(BIOS_DEBUG, "TIME STAMP "); break; case CBMEM_ID_MRCDATA: printk(BIOS_DEBUG, "MRC DATA "); break; case CBMEM_ID_CONSOLE: printk(BIOS_DEBUG, "CONSOLE "); break; + case CBMEM_ID_ELOG: printk(BIOS_DEBUG, "ELOG "); break; + case CBMEM_ID_COVERAGE: printk(BIOS_DEBUG, "COVERAGE "); break; default: printk(BIOS_DEBUG, "%08x ", cbmem_toc[i].id); } printk(BIOS_DEBUG, "%08llx ", cbmem_toc[i].base); diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c new file mode 100644 index 0000000..7c069cb --- /dev/null +++ b/src/lib/gcov-glue.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +typedef struct file { + uint32_t magic; + struct file *next; + char *filename; + char *data; + int offset; + int len; +} FILE; + +#define SEEK_SET 0 /* Seek from beginning of file. */ + +#define DIR_SEPARATOR '/' +#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#define HAS_DRIVE_SPEC(f) (0) + +#define COVERAGE_SIZE (32*1024) + +static FILE *current_file = NULL; +static FILE *previous_file = NULL; + +static FILE *fopen(const char *path, const char *mode) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fopen %s with mode %s\n", + path, mode); +#endif + if (!current_file) { + current_file = cbmem_add(CBMEM_ID_COVERAGE, 32*1024); + } else { + previous_file = current_file; + current_file = (FILE *)(ALIGN(((unsigned long)previous_file->data + previous_file->len), 16)); + } + + // TODO check if we're at the end of the CBMEM region (ENOMEM) + if (current_file) { + current_file->magic = 0x584d4153; + current_file->next = NULL; + if (previous_file) + previous_file->next = current_file; + current_file->filename = (char *)¤t_file[1]; + strcpy(current_file->filename, path); + current_file->data = (char *)ALIGN(((unsigned long)current_file->filename + strlen(path) + 1), 16); + current_file->offset = 0; + current_file->len = 0; + } + + return current_file; +} + +static int fclose(FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fclose %s\n", stream->filename); +#endif + return 0; +} + +static int fseek(FILE *stream, long offset, int whence) +{ + /* fseek should only be called with offset==0 and whence==SEEK_SET + * to a freshly opened file. */ + gcc_assert (offset == 0 && whence == SEEK_SET); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fseek %s offset=%d whence=%d\n", + stream->filename, offset, whence); +#endif + return 0; +} + +static long ftell(FILE *stream) +{ + /* ftell should currently not be called */ + gcc_assert(0); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "ftell %s\n", stream->filename); +#endif + return 0; +} + +static size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fread: ptr=%p size=%zd nmemb=%zd FILE*=%p\n", + ptr, size, nmemb, stream); +#endif + return 0; +} + +static size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fwrite: %zd * 0x%zd bytes to file %s\n", + nmemb, size, stream->filename); +#endif + // TODO check if file is last opened file and fail otherwise. + + memcpy(stream->data + stream->offset, ptr, size * nmemb); + stream->len += (nmemb * size) - (stream->len - stream->offset); + stream->offset += nmemb * size; + return nmemb; +} + +static void setbuf(FILE *stream, char *buf) +{ + gcc_assert(buf == 0); +} + +void coverage_init(void) +{ + extern long __CTOR_LIST__; + typedef void (*func_ptr)(void) ; + func_ptr *ctor = (func_ptr*) &__CTOR_LIST__; + if (ctor == NULL) + return; + + for ( ; *ctor != (func_ptr) 0; ctor++) { + (*ctor)(); + } +} + +void __gcov_flush(void); +void coverage_exit(void) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "Syncing coverage data.\n"); +#endif + __gcov_flush(); +} + + diff --git a/src/lib/gcov-io.c b/src/lib/gcov-io.c new file mode 100644 index 0000000..d2fee03 --- /dev/null +++ b/src/lib/gcov-io.c @@ -0,0 +1,556 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007, + 2008 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Routines declared in gcov-io.h. This file should be #included by + another source file, after having #included gcov-io.h. */ + +#ifdef __COREBOOT__ + +#endif + +#if !IN_GCOV +static void gcov_write_block (unsigned); +static gcov_unsigned_t *gcov_write_words (unsigned); +#endif +static const gcov_unsigned_t *gcov_read_words (unsigned); +#if !IN_LIBGCOV +static void gcov_allocate (unsigned); +#endif + +static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +{ +#if !IN_LIBGCOV + if (gcov_var.endian) + { + value = (value >> 16) | (value << 16); + value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); + } +#endif + return value; +} + +/* Open a gcov file. NAME is the name of the file to open and MODE + indicates whether a new file should be created, or an existing file + opened. If MODE is >= 0 an existing file will be opened, if + possible, and if MODE is <= 0, a new file will be created. Use + MODE=0 to attempt to reopen an existing file and then fall back on + creating a new one. If MODE < 0, the file will be opened in + read-only mode. Otherwise it will be opened for modification. + Return zero on failure, >0 on opening an existing file and <0 on + creating a new one. */ + +GCOV_LINKAGE int +#if IN_LIBGCOV +gcov_open (const char *name) +#else +gcov_open (const char *name, int mode) +#endif +{ +#if IN_LIBGCOV + const int mode = 0; +#endif +#if GCOV_LOCKED + struct flock s_flock; + int fd; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif + + gcc_assert (!gcov_var.file); + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; +#if !IN_LIBGCOV + gcov_var.endian = 0; +#endif +#if GCOV_LOCKED + if (mode > 0) + { + /* Read-only mode - acquire a read-lock. */ + s_flock.l_type = F_RDLCK; + fd = open (name, O_RDONLY); + } + else + { + /* Write mode - acquire a write-lock. */ + s_flock.l_type = F_WRLCK; + fd = open (name, O_RDWR | O_CREAT, 0666); + } + if (fd < 0) + return 0; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; + + gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); + + if (!gcov_var.file) + { + close (fd); + return 0; + } + + if (mode > 0) + gcov_var.mode = 1; + else if (mode == 0) + { + struct stat st; + + if (fstat (fd, &st) < 0) + { + fclose (gcov_var.file); + gcov_var.file = 0; + return 0; + } + if (st.st_size != 0) + gcov_var.mode = 1; + else + gcov_var.mode = mode * 2 + 1; + } + else + gcov_var.mode = mode * 2 + 1; +#else + if (mode >= 0) + gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + + if (gcov_var.file) + gcov_var.mode = 1; + else if (mode <= 0) + { + gcov_var.file = fopen (name, "w+b"); + if (gcov_var.file) + gcov_var.mode = mode * 2 + 1; + } + if (!gcov_var.file) + return 0; +#endif + + setbuf (gcov_var.file, (char *)0); + + return 1; +} + +/* Close the current gcov file. Flushes data to disk. Returns nonzero + on failure or error flag set. */ + +GCOV_LINKAGE int +gcov_close (void) +{ + if (gcov_var.file) + { +#if !IN_GCOV + if (gcov_var.offset && gcov_var.mode < 0) + gcov_write_block (gcov_var.offset); +#endif + fclose (gcov_var.file); + gcov_var.file = 0; + gcov_var.length = 0; + } +#if !IN_LIBGCOV + free (gcov_var.buffer); + gcov_var.alloc = 0; + gcov_var.buffer = 0; +#endif + gcov_var.mode = 0; + return gcov_var.error; +} + +#if !IN_LIBGCOV +/* Check if MAGIC is EXPECTED. Use it to determine endianness of the + file. Returns +1 for same endian, -1 for other endian and zero for + not EXPECTED. */ + +GCOV_LINKAGE int +gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) +{ + if (magic == expected) + return 1; + magic = (magic >> 16) | (magic << 16); + magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); + if (magic == expected) + { + gcov_var.endian = 1; + return -1; + } + return 0; +} +#endif + +#if !IN_LIBGCOV +static void +gcov_allocate (unsigned length) +{ + size_t new_size = gcov_var.alloc; + + if (!new_size) + new_size = GCOV_BLOCK_SIZE; + new_size += length; + new_size *= 2; + + gcov_var.alloc = new_size; + gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); +} +#endif + +#if !IN_GCOV +/* Write out the current block, if needs be. */ + +static void +gcov_write_block (unsigned size) +{ + if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + gcov_var.error = 1; + gcov_var.start += size; + gcov_var.offset -= size; +} + +/* Allocate space to write BYTES bytes to the gcov file. Return a + pointer to those bytes, or NULL on failure. */ + +static gcov_unsigned_t * +gcov_write_words (unsigned words) +{ + gcov_unsigned_t *result; + + gcc_assert (gcov_var.mode < 0); +#if IN_LIBGCOV + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + { + gcov_write_block (GCOV_BLOCK_SIZE); + if (gcov_var.offset) + { + gcc_assert (gcov_var.offset == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); + } + } +#else + if (gcov_var.offset + words > gcov_var.alloc) + gcov_allocate (gcov_var.offset + words); +#endif + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + + return result; +} + +/* Write unsigned VALUE to coverage file. Sets error flag + appropriately. */ + +GCOV_LINKAGE void +gcov_write_unsigned (gcov_unsigned_t value) +{ + gcov_unsigned_t *buffer = gcov_write_words (1); + + buffer[0] = value; +} + +/* Write counter VALUE to coverage file. Sets error flag + appropriately. */ + +#if IN_LIBGCOV +GCOV_LINKAGE void +gcov_write_counter (gcov_type value) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = (gcov_unsigned_t) value; + if (sizeof (value) > sizeof (gcov_unsigned_t)) + buffer[1] = (gcov_unsigned_t) (value >> 32); + else + buffer[1] = 0; +} +#endif /* IN_LIBGCOV */ + +#if !IN_LIBGCOV +/* Write STRING to coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE void +gcov_write_string (const char *string) +{ + unsigned length = 0; + unsigned alloc = 0; + gcov_unsigned_t *buffer; + + if (string) + { + length = strlen (string); + alloc = (length + 4) >> 2; + } + + buffer = gcov_write_words (1 + alloc); + + buffer[0] = alloc; + buffer[alloc] = 0; + memcpy (&buffer[1], string, length); +} +#endif + +#if !IN_LIBGCOV +/* Write a tag TAG and reserve space for the record length. Return a + value to be used for gcov_write_length. */ + +GCOV_LINKAGE gcov_position_t +gcov_write_tag (gcov_unsigned_t tag) +{ + gcov_position_t result = gcov_var.start + gcov_var.offset; + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = 0; + + return result; +} + +/* Write a record length using POSITION, which was returned by + gcov_write_tag. The current file position is the end of the + record, and is restored before returning. Returns nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_length (gcov_position_t position) +{ + unsigned offset; + gcov_unsigned_t length; + gcov_unsigned_t *buffer; + + gcc_assert (gcov_var.mode < 0); + gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); + gcc_assert (position >= gcov_var.start); + offset = position - gcov_var.start; + length = gcov_var.offset - offset - 2; + buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; + buffer[1] = length; + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + gcov_write_block (gcov_var.offset); +} + +#else /* IN_LIBGCOV */ + +/* Write a tag TAG and length LENGTH. */ + +GCOV_LINKAGE void +gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = length; +} + +/* Write a summary structure to the gcov file. Return nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) +{ + unsigned ix; + const struct gcov_ctr_summary *csum; + + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); + gcov_write_unsigned (summary->checksum); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + gcov_write_unsigned (csum->num); + gcov_write_unsigned (csum->runs); + gcov_write_counter (csum->sum_all); + gcov_write_counter (csum->run_max); + gcov_write_counter (csum->sum_max); + } +} +#endif /* IN_LIBGCOV */ + +#endif /*!IN_GCOV */ + +/* Return a pointer to read BYTES bytes from the gcov file. Returns + NULL on failure (read past EOF). */ + +static const gcov_unsigned_t * +gcov_read_words (unsigned words) +{ + const gcov_unsigned_t *result; + unsigned excess = gcov_var.length - gcov_var.offset; + + gcc_assert (gcov_var.mode > 0); + if (excess < words) + { + gcov_var.start += gcov_var.offset; +#if IN_LIBGCOV + if (excess) + { + gcc_assert (excess == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); + } +#else + memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); +#endif + gcov_var.offset = 0; + gcov_var.length = excess; +#if IN_LIBGCOV + gcc_assert (!gcov_var.length || gcov_var.length == 1); + excess = GCOV_BLOCK_SIZE; +#else + if (gcov_var.length + words > gcov_var.alloc) + gcov_allocate (gcov_var.length + words); + excess = gcov_var.alloc - gcov_var.length; +#endif + excess = fread (gcov_var.buffer + gcov_var.length, + 1, excess << 2, gcov_var.file) >> 2; + gcov_var.length += excess; + if (gcov_var.length < words) + { + gcov_var.overread += words - gcov_var.length; + gcov_var.length = 0; + return 0; + } + } + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + return result; +} + +/* Read unsigned value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_unsigned (void) +{ + gcov_unsigned_t value; + const gcov_unsigned_t *buffer = gcov_read_words (1); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + return value; +} + +/* Read counter value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_type +gcov_read_counter (void) +{ + gcov_type value; + const gcov_unsigned_t *buffer = gcov_read_words (2); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + if (sizeof (value) > sizeof (gcov_unsigned_t)) + value |= ((gcov_type) from_file (buffer[1])) << 32; + else if (buffer[1]) + gcov_var.error = -1; + + return value; +} + +/* Read string from coverage file. Returns a pointer to a static + buffer, or NULL on empty string. You must copy the string before + calling another gcov function. */ + +#if !IN_LIBGCOV +GCOV_LINKAGE const char * +gcov_read_string (void) +{ + unsigned length = gcov_read_unsigned (); + + if (!length) + return 0; + + return (const char *) gcov_read_words (length); +} +#endif + +GCOV_LINKAGE void +gcov_read_summary (struct gcov_summary *summary) +{ + unsigned ix; + struct gcov_ctr_summary *csum; + + summary->checksum = gcov_read_unsigned (); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + csum->num = gcov_read_unsigned (); + csum->runs = gcov_read_unsigned (); + csum->sum_all = gcov_read_counter (); + csum->run_max = gcov_read_counter (); + csum->sum_max = gcov_read_counter (); + } +} + +#if !IN_LIBGCOV +/* Reset to a known position. BASE should have been obtained from + gcov_position, LENGTH should be a record length. */ + +GCOV_LINKAGE void +gcov_sync (gcov_position_t base, gcov_unsigned_t length) +{ + gcc_assert (gcov_var.mode > 0); + base += length; + if (base - gcov_var.start <= gcov_var.length) + gcov_var.offset = base - gcov_var.start; + else + { + gcov_var.offset = gcov_var.length = 0; + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; + } +} +#endif + +#if IN_LIBGCOV +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + gcc_assert (gcov_var.mode < 0); + if (gcov_var.offset) + gcov_write_block (gcov_var.offset); + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; +} +#endif + +#if IN_GCOV > 0 +/* Return the modification time of the current gcov file. */ + +GCOV_LINKAGE time_t +gcov_time (void) +{ + struct stat status; + + if (fstat (fileno (gcov_var.file), &status)) + return 0; + else + return status.st_mtime; +} +#endif /* IN_GCOV */ diff --git a/src/lib/gcov-io.h b/src/lib/gcov-io.h new file mode 100644 index 0000000..4502bd6 --- /dev/null +++ b/src/lib/gcov-io.h @@ -0,0 +1,639 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, + 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + + +/* Coverage information is held in two files. A notes file, which is + generated by the compiler, and a data file, which is generated by + the program under test. Both files use a similar structure. We do + not attempt to make these files backwards compatible with previous + versions, as you only need coverage information when developing a + program. We do hold version information, so that mismatches can be + detected, and we use a format that allows tools to skip information + they do not understand or are not interested in. + + Numbers are recorded in the 32 bit unsigned binary form of the + endianness of the machine generating the file. 64 bit numbers are + stored as two 32 bit numbers, the low part first. Strings are + padded with 1 to 4 NUL bytes, to bring the length up to a multiple + of 4. The number of 4 bytes is stored, followed by the padded + string. Zero length and NULL strings are simply stored as a length + of zero (they have no trailing NUL or padding). + + int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3 + int64: int32:low int32:high + string: int32:0 | int32:length char* char:0 padding + padding: | char:0 | char:0 char:0 | char:0 char:0 char:0 + item: int32 | int64 | string + + The basic format of the files is + + file : int32:magic int32:version int32:stamp record* + + The magic ident is different for the notes and the data files. The + magic ident is used to determine the endianness of the file, when + reading. The version is the same for both files and is derived + from gcc's version number. The stamp value is used to synchronize + note and data files and to synchronize merging within a data + file. It need not be an absolute time stamp, merely a ticker that + increments fast enough and cycles slow enough to distinguish + different compile/run/compile cycles. + + Although the ident and version are formally 32 bit numbers, they + are derived from 4 character ASCII strings. The version number + consists of the single character major version number, a two + character minor version number (leading zero for versions less than + 10), and a single character indicating the status of the release. + That will be 'e' experimental, 'p' prerelease and 'r' for release. + Because, by good fortune, these are in alphabetical order, string + collating can be used to compare version strings. Be aware that + the 'e' designation will (naturally) be unstable and might be + incompatible with itself. For gcc 3.4 experimental, it would be + '304e' (0x33303465). When the major version reaches 10, the + letters A-Z will be used. Assuming minor increments releases every + 6 months, we have to make a major increment every 50 years. + Assuming major increments releases every 5 years, we're ok for the + next 155 years -- good enough for me. + + A record has a tag, length and variable amount of data. + + record: header data + header: int32:tag int32:length + data: item* + + Records are not nested, but there is a record hierarchy. Tag + numbers reflect this hierarchy. Tags are unique across note and + data files. Some record types have a varying amount of data. The + LENGTH is the number of 4bytes that follow and is usually used to + determine how much data. The tag value is split into 4 8-bit + fields, one for each of four possible levels. The most significant + is allocated first. Unused levels are zero. Active levels are + odd-valued, so that the LSB of the level is one. A sub-level + incorporates the values of its superlevels. This formatting allows + you to determine the tag hierarchy, without understanding the tags + themselves, and is similar to the standard section numbering used + in technical documents. Level values [1..3f] are used for common + tags, values [41..9f] for the notes file and [a1..ff] for the data + file. + + The basic block graph file contains the following records + note: unit function-graph* + unit: header int32:checksum string:source + function-graph: announce_function basic_blocks {arcs | lines}* + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + string:name string:source int32:lineno + basic_block: header int32:flags* + arcs: header int32:block_no arc* + arc: int32:dest_block int32:flags + lines: header int32:block_no line* + int32:0 string:NULL + line: int32:line_no | int32:0 string:filename + + The BASIC_BLOCK record holds per-bb flags. The number of blocks + can be inferred from its data length. There is one ARCS record per + basic block. The number of arcs from a bb is implicit from the + data length. It enumerates the destination bb and per-arc flags. + There is one LINES record per basic block, it enumerates the source + lines which belong to that basic block. Source file names are + introduced by a line number of 0, following lines are from the new + source file. The initial source file for the function is NULL, but + the current source file should be remembered from one LINES record + to the next. The end of a block is indicated by an empty filename + - this does not reset the current source file. Note there is no + ordering of the ARCS and LINES records: they may be in any order, + interleaved in any manner. The current filename follows the order + the LINES records are stored in the file, *not* the ordering of the + blocks they are for. + + The data file contains the following records. + data: {unit summary:object summary:program* function-data*}* + unit: header int32:checksum + function-data: announce_function present counts + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + present: header int32:present + counts: header int64:count* + summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE + count-summary: int32:num int32:runs int64:sum + int64:max int64:sum_max + + The ANNOUNCE_FUNCTION record is the same as that in the note file, + but without the source location. The COUNTS gives the + counter values for instrumented features. The about the whole + program. The checksum is used for whole program summaries, and + disambiguates different programs which include the same + instrumented object file. There may be several program summaries, + each with a unique checksum. The object summary's checksum is + zero. Note that the data file might contain information from + several runs concatenated, or the data might be merged. + + This file is included by both the compiler, gcov tools and the + runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to + distinguish which case is which. If IN_LIBGCOV is nonzero, + libgcov is being built. If IN_GCOV is nonzero, the gcov tools are + being built. Otherwise the compiler is being built. IN_GCOV may be + positive or negative. If positive, we are compiling a tool that + requires additional functions (see the code for knowledge of what + those functions are). */ + +#ifndef GCC_GCOV_IO_H +#define GCC_GCOV_IO_H + +#ifdef __COREBOOT__ +#define GCOV_LINKAGE /* nothing */ +/* We need the definitions for + BITS_PER_UNIT and + LONG_LONG_TYPE_SIZE + They are defined in gcc/defaults.h and gcc/config/ + (like, gcc/config/i386/i386.h). And it can be overridden by setting + in build scripts. Here I hardcoded the value for x86. */ +#define BITS_PER_UNIT 8 +#define LONG_LONG_TYPE_SIZE 64 + +/* There are many gcc_assertions. Set the vaule to 1 if we want a warning + message if the assertion fails. */ +#ifndef ENABLE_ASSERT_CHECKING +#define ENABLE_ASSERT_CHECKING 1 +#endif +#endif /* __COREBOOT__ */ + +#if IN_LIBGCOV +/* About the target */ + +#if BITS_PER_UNIT == 8 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef unsigned gcov_position_t __attribute__ ((mode (SI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (DI))); +#else +typedef signed gcov_type __attribute__ ((mode (SI))); +#endif +#else +#if BITS_PER_UNIT == 16 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); +typedef unsigned gcov_position_t __attribute__ ((mode (HI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (SI))); +#else +typedef signed gcov_type __attribute__ ((mode (HI))); +#endif +#else +typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); +typedef unsigned gcov_position_t __attribute__ ((mode (QI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (HI))); +#else +typedef signed gcov_type __attribute__ ((mode (QI))); +#endif +#endif +#endif + + +#if defined (TARGET_POSIX_IO) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#else /* !IN_LIBGCOV */ +/* About the host */ + +typedef unsigned gcov_unsigned_t; +typedef unsigned gcov_position_t; +/* gcov_type is typedef'd elsewhere for the compiler */ +#if IN_GCOV +#define GCOV_LINKAGE static +typedef HOST_WIDEST_INT gcov_type; +#if IN_GCOV > 0 +#include +#endif +#else /*!IN_GCOV */ +#define GCOV_TYPE_SIZE (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32) +#endif + +#if defined (HOST_HAS_F_SETLKW) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#endif /* !IN_LIBGCOV */ + +/* In gcov we want function linkage to be static. In the compiler we want + it extern, so that they can be accessed from elsewhere. In libgcov we + need these functions to be extern, so prefix them with __gcov. In + libgcov they must also be hidden so that the instance in the executable + is not also used in a DSO. */ +#if IN_LIBGCOV + +#ifndef __COREBOOT__ +#include "tconfig.h" +#endif /* __COREBOOT__ */ + +#define gcov_var __gcov_var +#define gcov_open __gcov_open +#define gcov_close __gcov_close +#define gcov_write_tag_length __gcov_write_tag_length +#define gcov_position __gcov_position +#define gcov_seek __gcov_seek +#define gcov_rewrite __gcov_rewrite +#define gcov_is_error __gcov_is_error +#define gcov_write_unsigned __gcov_write_unsigned +#define gcov_write_counter __gcov_write_counter +#define gcov_write_summary __gcov_write_summary +#define gcov_read_unsigned __gcov_read_unsigned +#define gcov_read_counter __gcov_read_counter +#define gcov_read_summary __gcov_read_summary + +/* Poison these, so they don't accidentally slip in. */ +#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length +#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#else + +#define ATTRIBUTE_HIDDEN + +#endif + +#ifndef GCOV_LINKAGE +#define GCOV_LINKAGE extern +#endif + +/* File suffixes. */ +#define GCOV_DATA_SUFFIX ".gcda" +#define GCOV_NOTE_SUFFIX ".gcno" + +/* File magic. Must not be palindromes. */ +#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ +#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */ + +/* gcov-iov.h is automatically generated by the makefile from + version.c, it looks like + #define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef) +*/ +#include "gcov-iov.h" + +/* Convert a magic or version number to a 4 character string. */ +#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ + ((ARRAY)[0] = (char)((VALUE) >> 24), \ + (ARRAY)[1] = (char)((VALUE) >> 16), \ + (ARRAY)[2] = (char)((VALUE) >> 8), \ + (ARRAY)[3] = (char)((VALUE) >> 0)) + +/* The record tags. Values [1..3f] are for tags which may be in either + file. Values [41..9f] for those in the note file and [a1..ff] for + the data file. The tag value zero is used as an explicit end of + file marker -- it is not required to be present. */ + +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) +#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) +#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) +#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) +#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_SUMMARY_LENGTH \ + (1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2)) + +/* Counters that are collected. */ +#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ +#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be + summaried. */ +#define GCOV_FIRST_VALUE_COUNTER 1 /* The first of counters used for value + profiling. They must form a consecutive + interval and their order must match + the order of HIST_TYPEs in + value-prof.h. */ +#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */ +#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm + of a value. */ +#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */ +#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between + consecutive values of expression. */ + +#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */ +#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the + counter. */ +#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to + counter. */ +#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value + profiling. */ +#define GCOV_COUNTERS 8 + +/* Number of counters used for value profiling. */ +#define GCOV_N_VALUE_COUNTERS \ + (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) + + /* A list of human readable names of the counters */ +#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \ + "delta", "indirect_call", "average", "ior"} + + /* Names of merge functions for counters. */ +#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_single", \ + "__gcov_merge_delta", \ + "__gcov_merge_single", \ + "__gcov_merge_add", \ + "__gcov_merge_ior"} + +/* Convert a counter index to a tag. */ +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) +/* Convert a tag to a counter. */ +#define GCOV_COUNTER_FOR_TAG(TAG) \ + ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)) +/* Check whether a tag is a counter tag. */ +#define GCOV_TAG_IS_COUNTER(TAG) \ + (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) + +/* The tag level mask has 1's in the position of the inner levels, & + the lsb of the current level, and zero on the current and outer + levels. */ +#define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG)) + +/* Return nonzero if SUB is an immediate subtag of TAG. */ +#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \ + && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG))) + +/* Return nonzero if SUB is at a sublevel to TAG. */ +#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB)) + +/* Basic block flags. */ +#define GCOV_BLOCK_UNEXPECTED (1 << 1) + +/* Arc flags. */ +#define GCOV_ARC_ON_TREE (1 << 0) +#define GCOV_ARC_FAKE (1 << 1) +#define GCOV_ARC_FALLTHROUGH (1 << 2) + +/* Structured records. */ + +/* Cumulative counter data. */ +struct gcov_ctr_summary +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_unsigned_t runs; /* number of program runs */ + gcov_type sum_all; /* sum of all counters accumulated. */ + gcov_type run_max; /* maximum value on a single run. */ + gcov_type sum_max; /* sum of individual run max values. */ +}; + +/* Object & program summary record. */ +struct gcov_summary +{ + gcov_unsigned_t checksum; /* checksum of program */ + struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; +}; + +/* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ + +#if IN_LIBGCOV +/* Information about counters for a single function. */ +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ +}; + +/* Information about a single function. This uses the trailing array + idiom. The number of counters is determined from the merge pointer + array in gcov_info. The key is used to detect which of a set of + comdat functions was selected -- it points to the gcov_info object + of the object file containing the selected comdat function. */ + +struct gcov_fn_info +{ + const struct gcov_info *key; /* comdat key */ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ + gcov_unsigned_t cfg_checksum; /* function cfg checksum */ + struct gcov_ctr_info ctrs[0]; /* instrumented counters */ +}; + +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; /* output file name */ + + gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for + unused) */ + + unsigned n_functions; /* number of functions */ + const struct gcov_fn_info *const *functions; /* pointer to pointers + to function information */ +}; + +/* Register a new object file module. */ +extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + +#ifndef __COREBOOT__ +/* Called before fork, to avoid double counting. */ +extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; +#endif + +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common value. */ +extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common difference between + consecutive values. */ +extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function that just ors the counters together. */ +extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The profiler functions. */ +extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); +extern void __gcov_pow2_profiler (gcov_type *, gcov_type); +extern void __gcov_one_value_profiler (gcov_type *, gcov_type); +extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *); +extern void __gcov_average_profiler (gcov_type *, gcov_type); +extern void __gcov_ior_profiler (gcov_type *, gcov_type); + +#ifndef inhibit_libc +/* The wrappers around some library functions.. */ +extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; +extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execve (const char *, char *const [], char *const []) + ATTRIBUTE_HIDDEN; +#endif + +#endif /* IN_LIBGCOV */ + +#if IN_LIBGCOV >= 0 + +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var ATTRIBUTE_HIDDEN; + +/* Functions for reading and writing gcov files. In libgcov you can + open the file for reading then writing. Elsewhere you can open the + file either for reading or for writing. When reading a file you may + use the gcov_read_* functions, gcov_sync, gcov_position, & + gcov_error. When writing a file you may use the gcov_write + functions, gcov_seek & gcov_error. When a file is to be rewritten + you use the functions for reading, then gcov_rewrite then the + functions for writing. Your file may become corrupted if you break + these invariants. */ +#if IN_LIBGCOV +GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; +#else +GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); +GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); +#endif +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; + +/* Available everywhere. */ +static gcov_position_t gcov_position (void); +static int gcov_is_error (void); + +GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; + +#if IN_LIBGCOV +/* Available only in libgcov */ +GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, + const struct gcov_summary *) + ATTRIBUTE_HIDDEN; +static void gcov_rewrite (void); +GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; +#else +/* Available outside libgcov */ +GCOV_LINKAGE const char *gcov_read_string (void); +GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, + gcov_unsigned_t /*length */); +#endif + +#if !IN_GCOV +/* Available outside gcov */ +GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +#endif + +#if !IN_GCOV && !IN_LIBGCOV +/* Available only in compiler */ +GCOV_LINKAGE void gcov_write_string (const char *); +GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); +GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); +#endif + +#if IN_GCOV > 0 +/* Available in gcov */ +GCOV_LINKAGE time_t gcov_time (void); +#endif + +/* Save the current position in the gcov file. */ + +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ + +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ + +static inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + +#endif /* IN_LIBGCOV >= 0 */ + +#endif /* GCC_GCOV_IO_H */ diff --git a/src/lib/gcov-iov.h b/src/lib/gcov-iov.h new file mode 100644 index 0000000..09951fb --- /dev/null +++ b/src/lib/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `4.7.2 (4 7) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3430372a) /* 407* */ diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 206e82b..eed243a 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -42,6 +42,7 @@ it with the version available from LANL. #if CONFIG_WRITE_HIGH_TABLES #include #endif +#include #include /** @@ -62,6 +63,10 @@ void hardwaremain(int boot_complete) timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); +#if CONFIG_COVERAGE + coverage_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); diff --git a/src/lib/libgcov.c b/src/lib/libgcov.c new file mode 100644 index 0000000..a32ce55 --- /dev/null +++ b/src/lib/libgcov.c @@ -0,0 +1,1158 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define __COREBOOT__ +#ifdef __COREBOOT__ +#include +#include +#include +#include +typedef s32 pid_t; +#define gcc_assert(x) ASSERT(x) +#define fprintf(file, x...) printk(BIOS_ERR, x) +#define alloca(size) __builtin_alloca (size) +#include "gcov-glue.c" + +/* Define MACROs to be used by coreboot compilation. */ +# define L_gcov +# define L_gcov_interval_profiler +# define L_gcov_pow2_profiler +# define L_gcov_one_value_profiler +# define L_gcov_indirect_call_profiler +# define L_gcov_average_profiler +# define L_gcov_ior_profiler + +# define HAVE_CC_TLS 0 +# define __GCOV_KERNEL__ + +# define IN_LIBGCOV 1 +# define IN_GCOV 0 +#else /* __COREBOOT__ */ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#endif /* __COREBOOT__ */ + +#ifndef __COREBOOT__ +#if defined(inhibit_libc) +#define IN_LIBGCOV (-1) +#else +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include +#define IN_LIBGCOV 1 +#if defined(L_gcov) +#define GCOV_LINKAGE /* nothing */ +#endif +#endif +#endif /* __COREBOOT__ */ +#include "gcov-io.h" + +#if defined(inhibit_libc) +/* If libc and its header files are not available, provide dummy functions. */ + +#ifdef L_gcov +void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} +void __gcov_flush (void) {} +#endif + +#ifdef L_gcov_merge_add +void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_single +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_delta +void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#else + +#ifndef __COREBOOT__ +#include +#if GCOV_LOCKED +#include +#include +#include +#endif +#else +void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif /* __COREBOOT__ */ + +#ifdef L_gcov +#include "gcov-io.c" + +struct gcov_fn_buffer +{ + struct gcov_fn_buffer *next; + unsigned fn_ix; + struct gcov_fn_info info; + /* note gcov_fn_info ends in a trailing array. */ +}; + +/* Chain of per-object gcov structures. */ +static struct gcov_info *gcov_list; + +/* Size of the longest file name. */ +static size_t gcov_max_filename = 0; + +/* Make sure path component of the given FILENAME exists, create + missing directories. FILENAME must be writable. + Returns zero on success, or -1 if an error occurred. */ + +static int +create_file_directory (char *filename) +{ +#ifdef __COREBOOT__ + (void) filename; + return 0; +#else +#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +#else + char *s; + + s = filename; + + if (HAS_DRIVE_SPEC(s)) + s += 2; + if (IS_DIR_SEPARATOR(*s)) + ++s; + for (; *s != '\0'; s++) + if (IS_DIR_SEPARATOR(*s)) + { + char sep = *s; + *s = '\0'; + + /* Try to make directory if it doesn't already exist. */ + if (access (filename, F_OK) == -1 +#ifdef TARGET_POSIX_IO + && mkdir (filename, 0755) == -1 +#else + && mkdir (filename) == -1 +#endif + /* The directory might have been made by another process. */ + && errno != EEXIST) + { + fprintf (stderr, "profiling:%s:Cannot create directory\n", + filename); + *s = sep; + return -1; + }; + + *s = sep; + }; + return 0; +#endif +#endif +} + +static struct gcov_fn_buffer * +free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, + unsigned limit) +{ + struct gcov_fn_buffer *next; + unsigned ix, n_ctr = 0; + + if (!buffer) + return 0; + next = buffer->next; + + for (ix = 0; ix != limit; ix++) + if (gi_ptr->merge[ix]) + free (buffer->info.ctrs[n_ctr++].values); + free (buffer); + return next; +} + +static struct gcov_fn_buffer ** +buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, + struct gcov_fn_buffer **end_ptr, unsigned fn_ix) +{ + unsigned n_ctrs = 0, ix = 0; + struct gcov_fn_buffer *fn_buffer; + unsigned len; + + for (ix = GCOV_COUNTERS; ix--;) + if (gi_ptr->merge[ix]) + n_ctrs++; + + len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; + fn_buffer = (struct gcov_fn_buffer *)malloc (len); + + if (!fn_buffer) + goto fail; + + fn_buffer->next = 0; + fn_buffer->fn_ix = fn_ix; + fn_buffer->info.ident = gcov_read_unsigned (); + fn_buffer->info.lineno_checksum = gcov_read_unsigned (); + fn_buffer->info.cfg_checksum = gcov_read_unsigned (); + + for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) + { + gcov_unsigned_t length; + gcov_type *values; + + if (!gi_ptr->merge[ix]) + continue; + + if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) + { + len = 0; + goto fail; + } + + length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); + len = length * sizeof (gcov_type); + values = (gcov_type *)malloc (len); + if (!values) + goto fail; + + fn_buffer->info.ctrs[n_ctrs].num = length; + fn_buffer->info.ctrs[n_ctrs].values = values; + + while (length--) + *values++ = gcov_read_counter (); + n_ctrs++; + } + + *end_ptr = fn_buffer; + return &fn_buffer->next; + +fail: + fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix, + len ? "cannot allocate" : "counter mismatch", len ? len : ix); + + return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); +} + +/* Add an unsigned value to the current crc */ + +static gcov_unsigned_t +crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) +{ + unsigned ix; + + for (ix = 32; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; + crc32 <<= 1; + crc32 ^= feedback; + } + + return crc32; +} + +/* Check if VERSION of the info block PTR matches libgcov one. + Return 1 on success, or zero in case of versions mismatch. + If FILENAME is not NULL, its value used for reporting purposes + instead of value from the info block. */ + +static int +gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, + const char *filename) +{ + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fprintf (stderr, + "profiling:%s:Version mismatch - expected %.4s got %.4s\n", + filename? filename : ptr->filename, e, v); + return 0; + } + return 1; +} + +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. We use this + program's checksum to make sure we only accumulate whole program + statistics to the correct summary. An object file might be embedded + in two separate programs, and we must keep the two program + summaries separate. */ + +static void +gcov_exit (void) +{ + struct gcov_info *gi_ptr; + const struct gcov_fn_info *gfi_ptr; + struct gcov_summary this_prg; /* summary for program. */ + struct gcov_summary all_prg; /* summary for all instances of program. */ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; + int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; + size_t prefix_length; + char *gi_filename, *gi_filename_up; + gcov_unsigned_t crc32 = 0; + + memset (&all_prg, 0, sizeof (all_prg)); + /* Find the totals for this execution. */ + memset (&this_prg, 0, sizeof (this_prg)); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); + crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); + + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (gfi_ptr && gfi_ptr->key != gi_ptr) + gfi_ptr = 0; + + crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); + crc32 = crc32_unsigned (crc32, + gfi_ptr ? gfi_ptr->lineno_checksum : 0); + if (!gfi_ptr) + continue; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + cs_ptr = &this_prg.ctrs[t_ix]; + cs_ptr->num += ci_ptr->num; + crc32 = crc32_unsigned (crc32, ci_ptr->num); + + for (c_num = 0; c_num < ci_ptr->num; c_num++) + { + cs_ptr->sum_all += ci_ptr->values[c_num]; + if (cs_ptr->run_max < ci_ptr->values[c_num]) + cs_ptr->run_max = ci_ptr->values[c_num]; + } + ci_ptr++; + } + } + } + +#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); + if (tmp) + { + gcov_prefix_strip = atoi (tmp); + /* Do not consider negative values. */ + if (gcov_prefix_strip < 0) + gcov_prefix_strip = 0; + } + } + + /* Get file name relocation prefix. Non-absolute values are ignored. */ + gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix) + { + prefix_length = strlen(gcov_prefix); + + /* Remove an unnecessary trailing '/' */ + if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; + } + else +#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume + relative. */ + if (gcov_prefix_strip != 0 && prefix_length == 0) + { + gcov_prefix = "."; + prefix_length = 1; + } + /* Allocate and initialize the filename scratch space plus one. */ + gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); + if (prefix_length) + memcpy (gi_filename, gcov_prefix, prefix_length); + gi_filename_up = gi_filename + prefix_length; + + /* Now merge each file. */ + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned n_counts; + struct gcov_summary prg; /* summary for this object over all + program. */ + struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all; + int error = 0; + gcov_unsigned_t tag, length; + gcov_position_t summary_pos = 0; + gcov_position_t eof_pos = 0; + const char *fname, *s; + struct gcov_fn_buffer *fn_buffer = 0; + struct gcov_fn_buffer **fn_tail = &fn_buffer; + + fname = gi_ptr->filename; + + /* Avoid to add multiple drive letters into combined path. */ + if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) + fname += 2; + + /* Build relocated filename, stripping off leading + directories from the initial filename if requested. */ + if (gcov_prefix_strip > 0) + { + int level = 0; + s = fname; + if (IS_DIR_SEPARATOR(*s)) + ++s; + + /* Skip selected directory levels. */ + for (; (*s != '\0') && (level < gcov_prefix_strip); s++) + if (IS_DIR_SEPARATOR(*s)) + { + fname = s; + level++; + } + } + + /* Update complete filename with stripped original. */ + if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + { + /* If prefix is given, add directory separator. */ + strcpy (gi_filename_up, "/"); + strcpy (gi_filename_up + 1, fname); + } + else + strcpy (gi_filename_up, fname); + + if (!gcov_open (gi_filename)) + { + /* Open failed likely due to missed directory. + Create directory and retry to open file. */ + if (create_file_directory (gi_filename)) + { + fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + continue; + } + if (!gcov_open (gi_filename)) + { + fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + continue; + } + } + + tag = gcov_read_unsigned (); + if (tag) + { + /* Merge data from file. */ + if (tag != GCOV_DATA_MAGIC) + { + fprintf (stderr, "profiling:%s:Not a gcov data file\n", + gi_filename); + goto read_fatal; + } + length = gcov_read_unsigned (); + if (!gcov_version (gi_ptr, length, gi_filename)) + goto read_fatal; + + length = gcov_read_unsigned (); + if (length != gi_ptr->stamp) + /* Read from a different compilation. Overwrite the file. */ + goto rewrite; + + /* Look for program summary. */ + for (f_ix = 0;;) + { + struct gcov_summary tmp; + + eof_pos = gcov_position (); + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_PROGRAM_SUMMARY) + break; + + f_ix--; + length = gcov_read_unsigned (); + if (length != GCOV_TAG_SUMMARY_LENGTH) + goto read_mismatch; + gcov_read_summary (&tmp); + if ((error = gcov_is_error ())) + goto read_error; + if (summary_pos || tmp.checksum != crc32) + goto next_summary; + + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num) + goto next_summary; + prg = tmp; + summary_pos = eof_pos; + + next_summary:; + } + + /* Merge execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; + f_ix++, tag = gcov_read_unsigned ()) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (tag != GCOV_TAG_FUNCTION) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (!length) + /* This function did not appear in the other program. + We have nothing to merge. */ + continue; + + if (length != GCOV_TAG_FUNCTION_LENGTH) + goto read_mismatch; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + { + /* This function appears in the other program. We + need to buffer the information in order to write + it back out -- we'll be inserting data before + this point, so cannot simply keep the data in the + file. */ + fn_tail = buffer_fn_data (gi_filename, + gi_ptr, fn_tail, f_ix); + if (!fn_tail) + goto read_mismatch; + continue; + } + + length = gcov_read_unsigned (); + if (length != gfi_ptr->ident) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->lineno_checksum) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->cfg_checksum) + goto read_mismatch; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + gcov_merge_fn merge = gi_ptr->merge[t_ix]; + + if (!merge) + continue; + + tag = gcov_read_unsigned (); + length = gcov_read_unsigned (); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) + goto read_mismatch; + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } + if ((error = gcov_is_error ())) + goto read_error; + } + + if (tag) + { + read_mismatch:; + fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n", + gi_filename, f_ix >= 0 ? "function" : "summary", + f_ix < 0 ? -1 - f_ix : f_ix); + goto read_fatal; + } + } + goto rewrite; + + read_error:; + fprintf (stderr, "profiling:%s:%s merging\n", gi_filename, + error < 0 ? "Overflow": "Error"); + + goto read_fatal; + + rewrite:; + gcov_rewrite (); + if (!summary_pos) + { + memset (&prg, 0, sizeof (prg)); + summary_pos = eof_pos; + } + + /* Merge the summaries. */ + for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) + { + cs_prg = &prg.ctrs[t_ix]; + cs_tprg = &this_prg.ctrs[t_ix]; + cs_all = &all_prg.ctrs[t_ix]; + + if (gi_ptr->merge[t_ix]) + { + if (!cs_prg->runs++) + cs_prg->num = cs_tprg->num; + cs_prg->sum_all += cs_tprg->sum_all; + if (cs_prg->run_max < cs_tprg->run_max) + cs_prg->run_max = cs_tprg->run_max; + cs_prg->sum_max += cs_tprg->run_max; + } + else if (cs_prg->runs) + goto read_mismatch; + + if (!cs_all->runs && cs_prg->runs) + memcpy (cs_all, cs_prg, sizeof (*cs_all)); + else if (!all_prg.checksum + && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) + && memcmp (cs_all, cs_prg, sizeof (*cs_all))) + { + fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n", + gi_filename, GCOV_LOCKED + ? "" : " or concurrently updated without locking support"); + all_prg.checksum = ~0u; + } + } + + prg.checksum = crc32; + + /* Write out the data. */ + if (!eof_pos) + { + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); + } + + if (summary_pos) + gcov_seek (summary_pos); + + /* Generate whole program statistics. */ + gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg); + + if (summary_pos < eof_pos) + gcov_seek (eof_pos); + + /* Write execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + unsigned buffered = 0; + + if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix) + { + /* Buffered data from another program. */ + buffered = 1; + gfi_ptr = &fn_buffer->info; + length = GCOV_TAG_FUNCTION_LENGTH; + } + else + { + gfi_ptr = gi_ptr->functions[f_ix]; + if (gfi_ptr && gfi_ptr->key == gi_ptr) + length = GCOV_TAG_FUNCTION_LENGTH; + else + length = 0; + } + + gcov_write_tag_length (GCOV_TAG_FUNCTION, length); + if (!length) + continue; + + gcov_write_unsigned (gfi_ptr->ident); + gcov_write_unsigned (gfi_ptr->lineno_checksum); + gcov_write_unsigned (gfi_ptr->cfg_checksum); + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + n_counts = ci_ptr->num; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + gcov_type *c_ptr = ci_ptr->values; + while (n_counts--) + gcov_write_counter (*c_ptr++); + ci_ptr++; + } + if (buffered) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + } + + gcov_write_unsigned (0); + + read_fatal:; + while (fn_buffer) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + + if ((error = gcov_close ())) + fprintf (stderr, error < 0 ? + "profiling:%s:Overflow writing\n" : + "profiling:%s:Error writing\n", + gi_filename); + } +} + +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + +void +__gcov_init (struct gcov_info *info) +{ + if (!info->version || !info->n_functions) + return; + if (gcov_version (info, info->version, 0)) + { + size_t filename_length = strlen(info->filename); + + /* Refresh the longest file name information */ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + +#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); +#endif + + info->next = gcov_list; + gcov_list = info; + } + info->version = 0; +} + +/* Called before fork or exec - write out profile information gathered so + far and reset it to zero. This avoids duplication or loss of the + profile information gathered so far. */ + +void +__gcov_flush (void) +{ + const struct gcov_info *gi_ptr; + + gcov_exit (); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + +#endif /* L_gcov */ + +#ifdef L_gcov_merge_add +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_add (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters += gcov_read_counter (); +} +#endif /* L_gcov_merge_add */ + +#ifdef L_gcov_merge_ior +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_ior (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters |= gcov_read_counter (); +} +#endif + +#ifdef L_gcov_merge_single +/* The profile merging function for choosing the most common value. + * It is given an array COUNTERS of N_COUNTERS old counters and it + * reads the same number of counters from the gcov file. The counters + * are split into 3-tuples where the members of the tuple have + * meanings: + * + * -- the stored candidate on the most common value of the measured entity + * -- counter + * -- total number of evaluations of the value + */ +void +__gcov_merge_single (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 3)); + n_measures = n_counters / 3; + for (i = 0; i < n_measures; i++, counters += 3) + { + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[0] == value) + counters[1] += counter; + else if (counter > counters[1]) + { + counters[0] = value; + counters[1] = counter - counters[1]; + } + else + counters[1] -= counter; + counters[2] += all; + } +} +#endif /* L_gcov_merge_single */ + +#ifdef L_gcov_merge_delta +/* The profile merging function for choosing the most common + difference between two consecutive evaluations of the value. It is + given an array COUNTERS of N_COUNTERS old counters and it reads the + same number of counters from the gcov file. The counters are split + into 4-tuples where the members of the tuple have meanings: + + -- the last value of the measured entity + -- the stored candidate on the most common difference + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_delta (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 4)); + n_measures = n_counters / 4; + for (i = 0; i < n_measures; i++, counters += 4) + { + /* last = */ gcov_read_counter (); + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[1] == value) + counters[2] += counter; + else if (counter > counters[2]) + { + counters[1] = value; + counters[2] = counter - counters[2]; + } + else + counters[2] -= counter; + counters[3] += all; + } +} +#endif /* L_gcov_merge_delta */ + +#ifdef L_gcov_interval_profiler +/* If VALUE is in interval , then increases the + corresponding counter in COUNTERS. If the VALUE is above or below + the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased + instead. */ + +void +__gcov_interval_profiler (gcov_type *counters, gcov_type value, + int start, unsigned steps) +{ + gcov_type delta = value - start; + if (delta < 0) + counters[steps + 1]++; + else if (delta >= steps) + counters[steps]++; + else + counters[delta]++; +} +#endif + +#ifdef L_gcov_pow2_profiler +/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise + COUNTERS[0] is incremented. */ + +void +__gcov_pow2_profiler (gcov_type *counters, gcov_type value) +{ + if (value & (value - 1)) + counters[0]++; + else + counters[1]++; +} +#endif + +/* Tries to determine the most common value among its inputs. Checks if the + value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] + is incremented. If this is not the case and COUNTERS[1] is not zero, + COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and + VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this + function is called more than 50% of the time with one value, this value + will be in COUNTERS[0] in the end. + + In any case, COUNTERS[2] is incremented. */ + +static inline void +__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) +{ + if (value == counters[0]) + counters[1]++; + else if (counters[1] == 0) + { + counters[1] = 1; + counters[0] = value; + } + else + counters[1]--; + counters[2]++; +} + +#ifdef L_gcov_one_value_profiler +void +__gcov_one_value_profiler (gcov_type *counters, gcov_type value) +{ + __gcov_one_value_profiler_body (counters, value); +} +#endif + +#ifdef L_gcov_indirect_call_profiler + +/* By default, the C++ compiler will use function addresses in the + vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero + tells the compiler to use function descriptors instead. The value + of this macro says how many words wide the descriptor is (normally 2), + but it may be dependent on target flags. Since we do not have access + to the target flags here we just check to see if it is set and use + that to set VTABLE_USES_DESCRIPTORS to 0 or 1. + + It is assumed that the address of a function descriptor may be treated + as a pointer to a function. */ + +#ifdef TARGET_VTABLE_USES_DESCRIPTORS +#define VTABLE_USES_DESCRIPTORS 1 +#else +#define VTABLE_USES_DESCRIPTORS 0 +#endif + +/* Tries to determine the most common value among its inputs. */ +void +__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, + void* cur_func, void* callee_func) +{ + /* If the C++ virtual tables contain function descriptors then one + function may have multiple descriptors and we need to dereference + the descriptors to see if they point to the same function. */ + if (cur_func == callee_func + || (VTABLE_USES_DESCRIPTORS && callee_func + && *(void **) cur_func == *(void **) callee_func)) + __gcov_one_value_profiler_body (counter, value); +} +#endif + + +#ifdef L_gcov_average_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_average_profiler (gcov_type *counters, gcov_type value) +{ + counters[0] += value; + counters[1] ++; +} +#endif + +#ifdef L_gcov_ior_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_ior_profiler (gcov_type *counters, gcov_type value) +{ + *counters |= value; +} +#endif + +#ifdef L_gcov_fork +/* A wrapper for the fork function. Flushes the accumulated profiling data, so + that they are not counted twice. */ + +pid_t +__gcov_fork (void) +{ + __gcov_flush (); + return fork (); +} +#endif + +#ifdef L_gcov_execl +/* A wrapper for the execl function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execl (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execv (path, args); +} +#endif + +#ifdef L_gcov_execlp +/* A wrapper for the execlp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execlp (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execvp (path, args); +} +#endif + +#ifdef L_gcov_execle +/* A wrapper for the execle function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execle (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + char **envp; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + envp = va_arg (aq, char **); + va_end (aq); + + return execve (path, args, envp); +} +#endif + +#ifdef L_gcov_execv +/* A wrapper for the execv function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execv (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execv (path, argv); +} +#endif + +#ifdef L_gcov_execvp +/* A wrapper for the execvp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execvp (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execvp (path, argv); +} +#endif + +#ifdef L_gcov_execve +/* A wrapper for the execve function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execve (const char *path, char *const argv[], char *const envp[]) +{ + __gcov_flush (); + return execve (path, argv, envp); +} +#endif +#endif /* inhibit_libc */ diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 2556a14..c5fb62a 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -32,6 +32,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR @@ -518,6 +519,9 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) #if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); #endif +#if CONFIG_COVERAGE + coverage_exit(); +#endif /* Before we go off to run the payload, see if * we stayed within our bounds. diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index a777a8f..bc6bd6b 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define MAP_BYTES (1024*1024) @@ -82,7 +84,7 @@ static void *map_memory(u64 physical) /* Mapped memory must be aligned to page size */ p = physical & ~(page - 1); - debug("Mapping 1MB of physical memory at %zx.\n", p); + debug("Mapping 1MB of physical memory at 0x%zx.\n", p); v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); @@ -103,8 +105,13 @@ static void *map_memory(u64 physical) static void unmap_memory(void) { + if (mapped_virtual == NULL) { + fprintf(stderr, "Error unmapping memory\n"); + return; + } debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); munmap(mapped_virtual, MAP_BYTES); + mapped_virtual = NULL; } /* @@ -347,7 +354,7 @@ struct cbmem_entry { uint64_t size; }; -void dump_cbmem_toc(void) +static void dump_cbmem_toc(void) { int i; uint64_t start; @@ -374,7 +381,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_GDT: printf("GDT "); break; case CBMEM_ID_ACPI: printf("ACPI "); break; case CBMEM_ID_ACPI_GNVS: printf("ACPI GNVS "); break; - case CBMEM_ID_CBTABLE: printf("COREBOOTE "); break; + case CBMEM_ID_CBTABLE: printf("COREBOOT "); break; case CBMEM_ID_PIRQ: printf("IRQ TABLE "); break; case CBMEM_ID_MPTABLE: printf("SMP TABLE "); break; case CBMEM_ID_RESUME: printf("ACPI RESUME "); break; @@ -384,6 +391,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_MRCDATA: printf("MRC DATA "); break; case CBMEM_ID_CONSOLE: printf("CONSOLE "); break; case CBMEM_ID_ELOG: printf("ELOG "); break; + case CBMEM_ID_COVERAGE: printf("COVERAGE "); break; default: printf("%08x ", entries[i].id); break; } @@ -393,7 +401,111 @@ void dump_cbmem_toc(void) unmap_memory(); } -void print_version(void) +#define COVERAGE_MAGIC 0x584d4153 +struct file { + uint32_t magic; + uint32_t next; + uint32_t filename; + uint32_t data; + int offset; + int len; +}; + +static int mkpath(char *path, mode_t mode) +{ + assert (path && *path); + char *p; + for (p = strchr(path+1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) { + *p = '/'; + return -1; + } + } + *p = '/'; + } + return 0; +} + +static void dump_coverage(void) +{ + int i, found = 0; + uint64_t start; + struct cbmem_entry *entries; + void *coverage; + unsigned long phys_offset; +#define phys_to_virt(x) ((void *)(unsigned long)(x) + phys_offset) + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + for (i=0; imagic == COVERAGE_MAGIC) { + FILE *f; + char *filename; + + debug(" -> %s\n", (char *)phys_to_virt(file->filename)); + filename = strdup((char *)phys_to_virt(file->filename)); + if (mkpath(filename, 0755) == -1) { + perror("Directory for coverage data could " + "not be created"); + exit(1); + } + f = fopen(filename, "wb"); + if (!f) { + printf("Could not open %s: %s\n", + filename, strerror(errno)); + exit(1); + } + if (fwrite((void *)phys_to_virt(file->data), + file->len, 1, f) != 1) { + printf("Could not write to %s: %s\n", + filename, strerror(errno)); + exit(1); + } + fclose(f); + free(filename); + + if (file->next) + file = (struct file *)phys_to_virt(file->next); + else + file = NULL; + } + unmap_memory(); +} + +static void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); printf("Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.\n\n"); @@ -409,11 +521,12 @@ void print_version(void) "along with this program. If not, see .\n\n"); } -void print_usage(const char *name) +static void print_usage(const char *name) { - printf("usage: %s [-vh?]\n", name); + printf("usage: %s [-cCltVvh?]\n", name); printf("\n" " -c | --console: print cbmem console\n" + " -C | --coverage: dump coverage information\n" " -l | --list: print cbmem table of contents\n" " -t | --timestamps: print timestamp information\n" " -V | --verbose: verbose (debugging) output\n" @@ -430,12 +543,14 @@ int main(int argc, char** argv) int print_defaults = 1; int print_console = 0; + int print_coverage = 0; int print_list = 0; int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { {"console", 0, 0, 'c'}, + {"coverage", 0, 0, 'C'}, {"list", 0, 0, 'l'}, {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, @@ -443,13 +558,17 @@ int main(int argc, char** argv) {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cltVvh?", + while ((opt = getopt_long(argc, argv, "cCltVvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': print_console = 1; print_defaults = 0; break; + case 'C': + print_coverage = 1; + print_defaults = 0; + break; case 'l': print_list = 1; print_defaults = 0; @@ -490,6 +609,9 @@ int main(int argc, char** argv) if (print_console) dump_console(); + if (print_coverage) + dump_coverage(); + if (print_list) dump_cbmem_toc(); From gerrit at coreboot.org Wed Jan 9 01:29:58 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Wed, 9 Jan 2013 01:29:58 +0100 Subject: [coreboot] Patch set updated for coreboot: 98246d1 Implement GCC code coverage analysis References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2052 -gerrit commit 98246d1f12202900c9a7cbdd25de11b2d451da8f Author: Stefan Reinauer Date: Tue Dec 18 16:23:28 2012 -0800 Implement GCC code coverage analysis In order to provide some insight on what code is executed during coreboot's run time and how well our test scenarios work, this adds code coverage support to coreboot's ram stage. This should be easily adaptable for payloads, and maybe even romstage. See http://gcc.gnu.org/onlinedocs/gcc/Gcov.html for more information. To instrument coreboot, select CONFIG_COVERAGE ("Code coverage support") in Kconfig, and recompile coreboot. coreboot will then store its code coverage information into CBMEM, if possible. Then, run "cbmem -CV" as root on the target system running the instrumented coreboot binary. This will create a whole bunch of .gcda files that contain coverage information. Tar them up, copy them to your build system machine, and untar them. Then you can use your favorite coverage utility (gcov, lcov, ...) to visualize code coverage. There is no example run for coreboot's coverage yet. However, for a sneak peak of what will expect you, please take a look at OpenBIOS' fcode suite's coverage report: http://www.openfirmware.info/data/coverage-fcode-suite-1.0.2/ Change-Id: Ib287d8309878a1f5c4be770c38b1bc0bb3aa6ec7 Signed-off-by: Stefan Reinauer --- Makefile.inc | 3 + src/Kconfig | 18 + src/arch/armv7/Makefile.inc | 2 +- src/arch/armv7/coreboot_ram.ld | 8 + src/arch/x86/Makefile.inc | 2 +- src/arch/x86/boot/acpi.c | 4 + src/arch/x86/coreboot_ram.ld | 8 + src/include/cbmem.h | 1 + src/include/coverage.h | 21 + src/lib/Makefile.inc | 1 + src/lib/cbmem.c | 2 + src/lib/gcov-glue.c | 153 ++++++ src/lib/gcov-io.c | 556 +++++++++++++++++++ src/lib/gcov-io.h | 639 ++++++++++++++++++++++ src/lib/gcov-iov.h | 4 + src/lib/hardwaremain.c | 5 + src/lib/libgcov.c | 1158 ++++++++++++++++++++++++++++++++++++++++ src/lib/selfboot.c | 4 + util/cbmem/cbmem.c | 136 ++++- 19 files changed, 2716 insertions(+), 9 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index a066e25..3731797 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,6 +99,9 @@ romstage-S-ccopts:=-D__PRE_RAM__ ifeq ($(CONFIG_TRACE),y) ramstage-c-ccopts:= -finstrument-functions endif +ifeq ($(CONFIG_COVERAGE),y) +ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) diff --git a/src/Kconfig b/src/Kconfig index 0a94ed8..2c97327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,15 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail. +config COVERAGE + bool "Code coverage support" + depends on COMPILER_GCC + default n + help + Add code coverage support for coreboot. This will store code + coverage information in CBMEM for extraction from user space. + If unsure, say N. + endmenu source src/mainboard/Kconfig @@ -868,6 +877,15 @@ config TRACE the 0xaaaabbbb is the actual function and 0xccccdddd is EIP of calling function. Please note some printk releated functions are omitted from trace to have good looking console dumps. + +config DEBUG_COVERAGE + bool "Debug code coverage" + default n + depends on COVERAGE + help + If enabled, the code coverage hooks in coreboot will output some + information about the coverage data that is dumped. + endmenu # These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..4a836d1 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -121,7 +121,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m -m armelf_linux_eabi -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --wrap __uidiv --wrap __do_div64 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/armv7/coreboot_ram.ld b/src/arch/armv7/coreboot_ram.ld index 57ddd03..329bce4 100644 --- a/src/arch/armv7/coreboot_ram.ld +++ b/src/arch/armv7/coreboot_ram.ld @@ -38,6 +38,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index e84700e..ea86f8f 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -166,7 +166,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 1d7dbf8..730e53e 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -36,6 +36,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -642,6 +643,9 @@ void suspend_resume(void) /* Call mainboard resume handler first, if defined. */ if (mainboard_suspend_resume) mainboard_suspend_resume(); +#if CONFIG_COVERAGE + coverage_exit(); +#endif post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); } diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld index a87a0e7..7ce0367 100644 --- a/src/arch/x86/coreboot_ram.ld +++ b/src/arch/x86/coreboot_ram.ld @@ -39,6 +39,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 21efe77..08e913a 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -55,6 +55,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_COVERAGE 0x47434f56 #define CBMEM_ID_NONE 0x00000000 #ifndef __ASSEMBLER__ diff --git a/src/include/coverage.h b/src/include/coverage.h new file mode 100644 index 0000000..e1c50c5 --- /dev/null +++ b/src/include/coverage.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void coverage_init(void); +void coverage_exit(void); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6b3f0d8..6796448 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -70,6 +70,7 @@ ramstage-$(CONFIG_USBDEBUG) += usbdebug.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index 7378d8c..f270f5d 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -260,6 +260,8 @@ void cbmem_list(void) case CBMEM_ID_TIMESTAMP: printk(BIOS_DEBUG, "TIME STAMP "); break; case CBMEM_ID_MRCDATA: printk(BIOS_DEBUG, "MRC DATA "); break; case CBMEM_ID_CONSOLE: printk(BIOS_DEBUG, "CONSOLE "); break; + case CBMEM_ID_ELOG: printk(BIOS_DEBUG, "ELOG "); break; + case CBMEM_ID_COVERAGE: printk(BIOS_DEBUG, "COVERAGE "); break; default: printk(BIOS_DEBUG, "%08x ", cbmem_toc[i].id); } printk(BIOS_DEBUG, "%08llx ", cbmem_toc[i].base); diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c new file mode 100644 index 0000000..7c069cb --- /dev/null +++ b/src/lib/gcov-glue.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +typedef struct file { + uint32_t magic; + struct file *next; + char *filename; + char *data; + int offset; + int len; +} FILE; + +#define SEEK_SET 0 /* Seek from beginning of file. */ + +#define DIR_SEPARATOR '/' +#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#define HAS_DRIVE_SPEC(f) (0) + +#define COVERAGE_SIZE (32*1024) + +static FILE *current_file = NULL; +static FILE *previous_file = NULL; + +static FILE *fopen(const char *path, const char *mode) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fopen %s with mode %s\n", + path, mode); +#endif + if (!current_file) { + current_file = cbmem_add(CBMEM_ID_COVERAGE, 32*1024); + } else { + previous_file = current_file; + current_file = (FILE *)(ALIGN(((unsigned long)previous_file->data + previous_file->len), 16)); + } + + // TODO check if we're at the end of the CBMEM region (ENOMEM) + if (current_file) { + current_file->magic = 0x584d4153; + current_file->next = NULL; + if (previous_file) + previous_file->next = current_file; + current_file->filename = (char *)¤t_file[1]; + strcpy(current_file->filename, path); + current_file->data = (char *)ALIGN(((unsigned long)current_file->filename + strlen(path) + 1), 16); + current_file->offset = 0; + current_file->len = 0; + } + + return current_file; +} + +static int fclose(FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fclose %s\n", stream->filename); +#endif + return 0; +} + +static int fseek(FILE *stream, long offset, int whence) +{ + /* fseek should only be called with offset==0 and whence==SEEK_SET + * to a freshly opened file. */ + gcc_assert (offset == 0 && whence == SEEK_SET); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fseek %s offset=%d whence=%d\n", + stream->filename, offset, whence); +#endif + return 0; +} + +static long ftell(FILE *stream) +{ + /* ftell should currently not be called */ + gcc_assert(0); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "ftell %s\n", stream->filename); +#endif + return 0; +} + +static size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fread: ptr=%p size=%zd nmemb=%zd FILE*=%p\n", + ptr, size, nmemb, stream); +#endif + return 0; +} + +static size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fwrite: %zd * 0x%zd bytes to file %s\n", + nmemb, size, stream->filename); +#endif + // TODO check if file is last opened file and fail otherwise. + + memcpy(stream->data + stream->offset, ptr, size * nmemb); + stream->len += (nmemb * size) - (stream->len - stream->offset); + stream->offset += nmemb * size; + return nmemb; +} + +static void setbuf(FILE *stream, char *buf) +{ + gcc_assert(buf == 0); +} + +void coverage_init(void) +{ + extern long __CTOR_LIST__; + typedef void (*func_ptr)(void) ; + func_ptr *ctor = (func_ptr*) &__CTOR_LIST__; + if (ctor == NULL) + return; + + for ( ; *ctor != (func_ptr) 0; ctor++) { + (*ctor)(); + } +} + +void __gcov_flush(void); +void coverage_exit(void) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "Syncing coverage data.\n"); +#endif + __gcov_flush(); +} + + diff --git a/src/lib/gcov-io.c b/src/lib/gcov-io.c new file mode 100644 index 0000000..d2fee03 --- /dev/null +++ b/src/lib/gcov-io.c @@ -0,0 +1,556 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007, + 2008 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Routines declared in gcov-io.h. This file should be #included by + another source file, after having #included gcov-io.h. */ + +#ifdef __COREBOOT__ + +#endif + +#if !IN_GCOV +static void gcov_write_block (unsigned); +static gcov_unsigned_t *gcov_write_words (unsigned); +#endif +static const gcov_unsigned_t *gcov_read_words (unsigned); +#if !IN_LIBGCOV +static void gcov_allocate (unsigned); +#endif + +static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +{ +#if !IN_LIBGCOV + if (gcov_var.endian) + { + value = (value >> 16) | (value << 16); + value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); + } +#endif + return value; +} + +/* Open a gcov file. NAME is the name of the file to open and MODE + indicates whether a new file should be created, or an existing file + opened. If MODE is >= 0 an existing file will be opened, if + possible, and if MODE is <= 0, a new file will be created. Use + MODE=0 to attempt to reopen an existing file and then fall back on + creating a new one. If MODE < 0, the file will be opened in + read-only mode. Otherwise it will be opened for modification. + Return zero on failure, >0 on opening an existing file and <0 on + creating a new one. */ + +GCOV_LINKAGE int +#if IN_LIBGCOV +gcov_open (const char *name) +#else +gcov_open (const char *name, int mode) +#endif +{ +#if IN_LIBGCOV + const int mode = 0; +#endif +#if GCOV_LOCKED + struct flock s_flock; + int fd; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif + + gcc_assert (!gcov_var.file); + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; +#if !IN_LIBGCOV + gcov_var.endian = 0; +#endif +#if GCOV_LOCKED + if (mode > 0) + { + /* Read-only mode - acquire a read-lock. */ + s_flock.l_type = F_RDLCK; + fd = open (name, O_RDONLY); + } + else + { + /* Write mode - acquire a write-lock. */ + s_flock.l_type = F_WRLCK; + fd = open (name, O_RDWR | O_CREAT, 0666); + } + if (fd < 0) + return 0; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; + + gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); + + if (!gcov_var.file) + { + close (fd); + return 0; + } + + if (mode > 0) + gcov_var.mode = 1; + else if (mode == 0) + { + struct stat st; + + if (fstat (fd, &st) < 0) + { + fclose (gcov_var.file); + gcov_var.file = 0; + return 0; + } + if (st.st_size != 0) + gcov_var.mode = 1; + else + gcov_var.mode = mode * 2 + 1; + } + else + gcov_var.mode = mode * 2 + 1; +#else + if (mode >= 0) + gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + + if (gcov_var.file) + gcov_var.mode = 1; + else if (mode <= 0) + { + gcov_var.file = fopen (name, "w+b"); + if (gcov_var.file) + gcov_var.mode = mode * 2 + 1; + } + if (!gcov_var.file) + return 0; +#endif + + setbuf (gcov_var.file, (char *)0); + + return 1; +} + +/* Close the current gcov file. Flushes data to disk. Returns nonzero + on failure or error flag set. */ + +GCOV_LINKAGE int +gcov_close (void) +{ + if (gcov_var.file) + { +#if !IN_GCOV + if (gcov_var.offset && gcov_var.mode < 0) + gcov_write_block (gcov_var.offset); +#endif + fclose (gcov_var.file); + gcov_var.file = 0; + gcov_var.length = 0; + } +#if !IN_LIBGCOV + free (gcov_var.buffer); + gcov_var.alloc = 0; + gcov_var.buffer = 0; +#endif + gcov_var.mode = 0; + return gcov_var.error; +} + +#if !IN_LIBGCOV +/* Check if MAGIC is EXPECTED. Use it to determine endianness of the + file. Returns +1 for same endian, -1 for other endian and zero for + not EXPECTED. */ + +GCOV_LINKAGE int +gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) +{ + if (magic == expected) + return 1; + magic = (magic >> 16) | (magic << 16); + magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); + if (magic == expected) + { + gcov_var.endian = 1; + return -1; + } + return 0; +} +#endif + +#if !IN_LIBGCOV +static void +gcov_allocate (unsigned length) +{ + size_t new_size = gcov_var.alloc; + + if (!new_size) + new_size = GCOV_BLOCK_SIZE; + new_size += length; + new_size *= 2; + + gcov_var.alloc = new_size; + gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); +} +#endif + +#if !IN_GCOV +/* Write out the current block, if needs be. */ + +static void +gcov_write_block (unsigned size) +{ + if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + gcov_var.error = 1; + gcov_var.start += size; + gcov_var.offset -= size; +} + +/* Allocate space to write BYTES bytes to the gcov file. Return a + pointer to those bytes, or NULL on failure. */ + +static gcov_unsigned_t * +gcov_write_words (unsigned words) +{ + gcov_unsigned_t *result; + + gcc_assert (gcov_var.mode < 0); +#if IN_LIBGCOV + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + { + gcov_write_block (GCOV_BLOCK_SIZE); + if (gcov_var.offset) + { + gcc_assert (gcov_var.offset == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); + } + } +#else + if (gcov_var.offset + words > gcov_var.alloc) + gcov_allocate (gcov_var.offset + words); +#endif + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + + return result; +} + +/* Write unsigned VALUE to coverage file. Sets error flag + appropriately. */ + +GCOV_LINKAGE void +gcov_write_unsigned (gcov_unsigned_t value) +{ + gcov_unsigned_t *buffer = gcov_write_words (1); + + buffer[0] = value; +} + +/* Write counter VALUE to coverage file. Sets error flag + appropriately. */ + +#if IN_LIBGCOV +GCOV_LINKAGE void +gcov_write_counter (gcov_type value) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = (gcov_unsigned_t) value; + if (sizeof (value) > sizeof (gcov_unsigned_t)) + buffer[1] = (gcov_unsigned_t) (value >> 32); + else + buffer[1] = 0; +} +#endif /* IN_LIBGCOV */ + +#if !IN_LIBGCOV +/* Write STRING to coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE void +gcov_write_string (const char *string) +{ + unsigned length = 0; + unsigned alloc = 0; + gcov_unsigned_t *buffer; + + if (string) + { + length = strlen (string); + alloc = (length + 4) >> 2; + } + + buffer = gcov_write_words (1 + alloc); + + buffer[0] = alloc; + buffer[alloc] = 0; + memcpy (&buffer[1], string, length); +} +#endif + +#if !IN_LIBGCOV +/* Write a tag TAG and reserve space for the record length. Return a + value to be used for gcov_write_length. */ + +GCOV_LINKAGE gcov_position_t +gcov_write_tag (gcov_unsigned_t tag) +{ + gcov_position_t result = gcov_var.start + gcov_var.offset; + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = 0; + + return result; +} + +/* Write a record length using POSITION, which was returned by + gcov_write_tag. The current file position is the end of the + record, and is restored before returning. Returns nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_length (gcov_position_t position) +{ + unsigned offset; + gcov_unsigned_t length; + gcov_unsigned_t *buffer; + + gcc_assert (gcov_var.mode < 0); + gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); + gcc_assert (position >= gcov_var.start); + offset = position - gcov_var.start; + length = gcov_var.offset - offset - 2; + buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; + buffer[1] = length; + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + gcov_write_block (gcov_var.offset); +} + +#else /* IN_LIBGCOV */ + +/* Write a tag TAG and length LENGTH. */ + +GCOV_LINKAGE void +gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = length; +} + +/* Write a summary structure to the gcov file. Return nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) +{ + unsigned ix; + const struct gcov_ctr_summary *csum; + + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); + gcov_write_unsigned (summary->checksum); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + gcov_write_unsigned (csum->num); + gcov_write_unsigned (csum->runs); + gcov_write_counter (csum->sum_all); + gcov_write_counter (csum->run_max); + gcov_write_counter (csum->sum_max); + } +} +#endif /* IN_LIBGCOV */ + +#endif /*!IN_GCOV */ + +/* Return a pointer to read BYTES bytes from the gcov file. Returns + NULL on failure (read past EOF). */ + +static const gcov_unsigned_t * +gcov_read_words (unsigned words) +{ + const gcov_unsigned_t *result; + unsigned excess = gcov_var.length - gcov_var.offset; + + gcc_assert (gcov_var.mode > 0); + if (excess < words) + { + gcov_var.start += gcov_var.offset; +#if IN_LIBGCOV + if (excess) + { + gcc_assert (excess == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); + } +#else + memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); +#endif + gcov_var.offset = 0; + gcov_var.length = excess; +#if IN_LIBGCOV + gcc_assert (!gcov_var.length || gcov_var.length == 1); + excess = GCOV_BLOCK_SIZE; +#else + if (gcov_var.length + words > gcov_var.alloc) + gcov_allocate (gcov_var.length + words); + excess = gcov_var.alloc - gcov_var.length; +#endif + excess = fread (gcov_var.buffer + gcov_var.length, + 1, excess << 2, gcov_var.file) >> 2; + gcov_var.length += excess; + if (gcov_var.length < words) + { + gcov_var.overread += words - gcov_var.length; + gcov_var.length = 0; + return 0; + } + } + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + return result; +} + +/* Read unsigned value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_unsigned (void) +{ + gcov_unsigned_t value; + const gcov_unsigned_t *buffer = gcov_read_words (1); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + return value; +} + +/* Read counter value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_type +gcov_read_counter (void) +{ + gcov_type value; + const gcov_unsigned_t *buffer = gcov_read_words (2); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + if (sizeof (value) > sizeof (gcov_unsigned_t)) + value |= ((gcov_type) from_file (buffer[1])) << 32; + else if (buffer[1]) + gcov_var.error = -1; + + return value; +} + +/* Read string from coverage file. Returns a pointer to a static + buffer, or NULL on empty string. You must copy the string before + calling another gcov function. */ + +#if !IN_LIBGCOV +GCOV_LINKAGE const char * +gcov_read_string (void) +{ + unsigned length = gcov_read_unsigned (); + + if (!length) + return 0; + + return (const char *) gcov_read_words (length); +} +#endif + +GCOV_LINKAGE void +gcov_read_summary (struct gcov_summary *summary) +{ + unsigned ix; + struct gcov_ctr_summary *csum; + + summary->checksum = gcov_read_unsigned (); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + csum->num = gcov_read_unsigned (); + csum->runs = gcov_read_unsigned (); + csum->sum_all = gcov_read_counter (); + csum->run_max = gcov_read_counter (); + csum->sum_max = gcov_read_counter (); + } +} + +#if !IN_LIBGCOV +/* Reset to a known position. BASE should have been obtained from + gcov_position, LENGTH should be a record length. */ + +GCOV_LINKAGE void +gcov_sync (gcov_position_t base, gcov_unsigned_t length) +{ + gcc_assert (gcov_var.mode > 0); + base += length; + if (base - gcov_var.start <= gcov_var.length) + gcov_var.offset = base - gcov_var.start; + else + { + gcov_var.offset = gcov_var.length = 0; + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; + } +} +#endif + +#if IN_LIBGCOV +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + gcc_assert (gcov_var.mode < 0); + if (gcov_var.offset) + gcov_write_block (gcov_var.offset); + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; +} +#endif + +#if IN_GCOV > 0 +/* Return the modification time of the current gcov file. */ + +GCOV_LINKAGE time_t +gcov_time (void) +{ + struct stat status; + + if (fstat (fileno (gcov_var.file), &status)) + return 0; + else + return status.st_mtime; +} +#endif /* IN_GCOV */ diff --git a/src/lib/gcov-io.h b/src/lib/gcov-io.h new file mode 100644 index 0000000..4502bd6 --- /dev/null +++ b/src/lib/gcov-io.h @@ -0,0 +1,639 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, + 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + + +/* Coverage information is held in two files. A notes file, which is + generated by the compiler, and a data file, which is generated by + the program under test. Both files use a similar structure. We do + not attempt to make these files backwards compatible with previous + versions, as you only need coverage information when developing a + program. We do hold version information, so that mismatches can be + detected, and we use a format that allows tools to skip information + they do not understand or are not interested in. + + Numbers are recorded in the 32 bit unsigned binary form of the + endianness of the machine generating the file. 64 bit numbers are + stored as two 32 bit numbers, the low part first. Strings are + padded with 1 to 4 NUL bytes, to bring the length up to a multiple + of 4. The number of 4 bytes is stored, followed by the padded + string. Zero length and NULL strings are simply stored as a length + of zero (they have no trailing NUL or padding). + + int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3 + int64: int32:low int32:high + string: int32:0 | int32:length char* char:0 padding + padding: | char:0 | char:0 char:0 | char:0 char:0 char:0 + item: int32 | int64 | string + + The basic format of the files is + + file : int32:magic int32:version int32:stamp record* + + The magic ident is different for the notes and the data files. The + magic ident is used to determine the endianness of the file, when + reading. The version is the same for both files and is derived + from gcc's version number. The stamp value is used to synchronize + note and data files and to synchronize merging within a data + file. It need not be an absolute time stamp, merely a ticker that + increments fast enough and cycles slow enough to distinguish + different compile/run/compile cycles. + + Although the ident and version are formally 32 bit numbers, they + are derived from 4 character ASCII strings. The version number + consists of the single character major version number, a two + character minor version number (leading zero for versions less than + 10), and a single character indicating the status of the release. + That will be 'e' experimental, 'p' prerelease and 'r' for release. + Because, by good fortune, these are in alphabetical order, string + collating can be used to compare version strings. Be aware that + the 'e' designation will (naturally) be unstable and might be + incompatible with itself. For gcc 3.4 experimental, it would be + '304e' (0x33303465). When the major version reaches 10, the + letters A-Z will be used. Assuming minor increments releases every + 6 months, we have to make a major increment every 50 years. + Assuming major increments releases every 5 years, we're ok for the + next 155 years -- good enough for me. + + A record has a tag, length and variable amount of data. + + record: header data + header: int32:tag int32:length + data: item* + + Records are not nested, but there is a record hierarchy. Tag + numbers reflect this hierarchy. Tags are unique across note and + data files. Some record types have a varying amount of data. The + LENGTH is the number of 4bytes that follow and is usually used to + determine how much data. The tag value is split into 4 8-bit + fields, one for each of four possible levels. The most significant + is allocated first. Unused levels are zero. Active levels are + odd-valued, so that the LSB of the level is one. A sub-level + incorporates the values of its superlevels. This formatting allows + you to determine the tag hierarchy, without understanding the tags + themselves, and is similar to the standard section numbering used + in technical documents. Level values [1..3f] are used for common + tags, values [41..9f] for the notes file and [a1..ff] for the data + file. + + The basic block graph file contains the following records + note: unit function-graph* + unit: header int32:checksum string:source + function-graph: announce_function basic_blocks {arcs | lines}* + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + string:name string:source int32:lineno + basic_block: header int32:flags* + arcs: header int32:block_no arc* + arc: int32:dest_block int32:flags + lines: header int32:block_no line* + int32:0 string:NULL + line: int32:line_no | int32:0 string:filename + + The BASIC_BLOCK record holds per-bb flags. The number of blocks + can be inferred from its data length. There is one ARCS record per + basic block. The number of arcs from a bb is implicit from the + data length. It enumerates the destination bb and per-arc flags. + There is one LINES record per basic block, it enumerates the source + lines which belong to that basic block. Source file names are + introduced by a line number of 0, following lines are from the new + source file. The initial source file for the function is NULL, but + the current source file should be remembered from one LINES record + to the next. The end of a block is indicated by an empty filename + - this does not reset the current source file. Note there is no + ordering of the ARCS and LINES records: they may be in any order, + interleaved in any manner. The current filename follows the order + the LINES records are stored in the file, *not* the ordering of the + blocks they are for. + + The data file contains the following records. + data: {unit summary:object summary:program* function-data*}* + unit: header int32:checksum + function-data: announce_function present counts + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + present: header int32:present + counts: header int64:count* + summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE + count-summary: int32:num int32:runs int64:sum + int64:max int64:sum_max + + The ANNOUNCE_FUNCTION record is the same as that in the note file, + but without the source location. The COUNTS gives the + counter values for instrumented features. The about the whole + program. The checksum is used for whole program summaries, and + disambiguates different programs which include the same + instrumented object file. There may be several program summaries, + each with a unique checksum. The object summary's checksum is + zero. Note that the data file might contain information from + several runs concatenated, or the data might be merged. + + This file is included by both the compiler, gcov tools and the + runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to + distinguish which case is which. If IN_LIBGCOV is nonzero, + libgcov is being built. If IN_GCOV is nonzero, the gcov tools are + being built. Otherwise the compiler is being built. IN_GCOV may be + positive or negative. If positive, we are compiling a tool that + requires additional functions (see the code for knowledge of what + those functions are). */ + +#ifndef GCC_GCOV_IO_H +#define GCC_GCOV_IO_H + +#ifdef __COREBOOT__ +#define GCOV_LINKAGE /* nothing */ +/* We need the definitions for + BITS_PER_UNIT and + LONG_LONG_TYPE_SIZE + They are defined in gcc/defaults.h and gcc/config/ + (like, gcc/config/i386/i386.h). And it can be overridden by setting + in build scripts. Here I hardcoded the value for x86. */ +#define BITS_PER_UNIT 8 +#define LONG_LONG_TYPE_SIZE 64 + +/* There are many gcc_assertions. Set the vaule to 1 if we want a warning + message if the assertion fails. */ +#ifndef ENABLE_ASSERT_CHECKING +#define ENABLE_ASSERT_CHECKING 1 +#endif +#endif /* __COREBOOT__ */ + +#if IN_LIBGCOV +/* About the target */ + +#if BITS_PER_UNIT == 8 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef unsigned gcov_position_t __attribute__ ((mode (SI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (DI))); +#else +typedef signed gcov_type __attribute__ ((mode (SI))); +#endif +#else +#if BITS_PER_UNIT == 16 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); +typedef unsigned gcov_position_t __attribute__ ((mode (HI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (SI))); +#else +typedef signed gcov_type __attribute__ ((mode (HI))); +#endif +#else +typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); +typedef unsigned gcov_position_t __attribute__ ((mode (QI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (HI))); +#else +typedef signed gcov_type __attribute__ ((mode (QI))); +#endif +#endif +#endif + + +#if defined (TARGET_POSIX_IO) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#else /* !IN_LIBGCOV */ +/* About the host */ + +typedef unsigned gcov_unsigned_t; +typedef unsigned gcov_position_t; +/* gcov_type is typedef'd elsewhere for the compiler */ +#if IN_GCOV +#define GCOV_LINKAGE static +typedef HOST_WIDEST_INT gcov_type; +#if IN_GCOV > 0 +#include +#endif +#else /*!IN_GCOV */ +#define GCOV_TYPE_SIZE (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32) +#endif + +#if defined (HOST_HAS_F_SETLKW) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#endif /* !IN_LIBGCOV */ + +/* In gcov we want function linkage to be static. In the compiler we want + it extern, so that they can be accessed from elsewhere. In libgcov we + need these functions to be extern, so prefix them with __gcov. In + libgcov they must also be hidden so that the instance in the executable + is not also used in a DSO. */ +#if IN_LIBGCOV + +#ifndef __COREBOOT__ +#include "tconfig.h" +#endif /* __COREBOOT__ */ + +#define gcov_var __gcov_var +#define gcov_open __gcov_open +#define gcov_close __gcov_close +#define gcov_write_tag_length __gcov_write_tag_length +#define gcov_position __gcov_position +#define gcov_seek __gcov_seek +#define gcov_rewrite __gcov_rewrite +#define gcov_is_error __gcov_is_error +#define gcov_write_unsigned __gcov_write_unsigned +#define gcov_write_counter __gcov_write_counter +#define gcov_write_summary __gcov_write_summary +#define gcov_read_unsigned __gcov_read_unsigned +#define gcov_read_counter __gcov_read_counter +#define gcov_read_summary __gcov_read_summary + +/* Poison these, so they don't accidentally slip in. */ +#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length +#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#else + +#define ATTRIBUTE_HIDDEN + +#endif + +#ifndef GCOV_LINKAGE +#define GCOV_LINKAGE extern +#endif + +/* File suffixes. */ +#define GCOV_DATA_SUFFIX ".gcda" +#define GCOV_NOTE_SUFFIX ".gcno" + +/* File magic. Must not be palindromes. */ +#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ +#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */ + +/* gcov-iov.h is automatically generated by the makefile from + version.c, it looks like + #define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef) +*/ +#include "gcov-iov.h" + +/* Convert a magic or version number to a 4 character string. */ +#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ + ((ARRAY)[0] = (char)((VALUE) >> 24), \ + (ARRAY)[1] = (char)((VALUE) >> 16), \ + (ARRAY)[2] = (char)((VALUE) >> 8), \ + (ARRAY)[3] = (char)((VALUE) >> 0)) + +/* The record tags. Values [1..3f] are for tags which may be in either + file. Values [41..9f] for those in the note file and [a1..ff] for + the data file. The tag value zero is used as an explicit end of + file marker -- it is not required to be present. */ + +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) +#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) +#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) +#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) +#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_SUMMARY_LENGTH \ + (1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2)) + +/* Counters that are collected. */ +#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ +#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be + summaried. */ +#define GCOV_FIRST_VALUE_COUNTER 1 /* The first of counters used for value + profiling. They must form a consecutive + interval and their order must match + the order of HIST_TYPEs in + value-prof.h. */ +#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */ +#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm + of a value. */ +#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */ +#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between + consecutive values of expression. */ + +#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */ +#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the + counter. */ +#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to + counter. */ +#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value + profiling. */ +#define GCOV_COUNTERS 8 + +/* Number of counters used for value profiling. */ +#define GCOV_N_VALUE_COUNTERS \ + (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) + + /* A list of human readable names of the counters */ +#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \ + "delta", "indirect_call", "average", "ior"} + + /* Names of merge functions for counters. */ +#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_single", \ + "__gcov_merge_delta", \ + "__gcov_merge_single", \ + "__gcov_merge_add", \ + "__gcov_merge_ior"} + +/* Convert a counter index to a tag. */ +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) +/* Convert a tag to a counter. */ +#define GCOV_COUNTER_FOR_TAG(TAG) \ + ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)) +/* Check whether a tag is a counter tag. */ +#define GCOV_TAG_IS_COUNTER(TAG) \ + (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) + +/* The tag level mask has 1's in the position of the inner levels, & + the lsb of the current level, and zero on the current and outer + levels. */ +#define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG)) + +/* Return nonzero if SUB is an immediate subtag of TAG. */ +#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \ + && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG))) + +/* Return nonzero if SUB is at a sublevel to TAG. */ +#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB)) + +/* Basic block flags. */ +#define GCOV_BLOCK_UNEXPECTED (1 << 1) + +/* Arc flags. */ +#define GCOV_ARC_ON_TREE (1 << 0) +#define GCOV_ARC_FAKE (1 << 1) +#define GCOV_ARC_FALLTHROUGH (1 << 2) + +/* Structured records. */ + +/* Cumulative counter data. */ +struct gcov_ctr_summary +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_unsigned_t runs; /* number of program runs */ + gcov_type sum_all; /* sum of all counters accumulated. */ + gcov_type run_max; /* maximum value on a single run. */ + gcov_type sum_max; /* sum of individual run max values. */ +}; + +/* Object & program summary record. */ +struct gcov_summary +{ + gcov_unsigned_t checksum; /* checksum of program */ + struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; +}; + +/* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ + +#if IN_LIBGCOV +/* Information about counters for a single function. */ +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ +}; + +/* Information about a single function. This uses the trailing array + idiom. The number of counters is determined from the merge pointer + array in gcov_info. The key is used to detect which of a set of + comdat functions was selected -- it points to the gcov_info object + of the object file containing the selected comdat function. */ + +struct gcov_fn_info +{ + const struct gcov_info *key; /* comdat key */ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ + gcov_unsigned_t cfg_checksum; /* function cfg checksum */ + struct gcov_ctr_info ctrs[0]; /* instrumented counters */ +}; + +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; /* output file name */ + + gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for + unused) */ + + unsigned n_functions; /* number of functions */ + const struct gcov_fn_info *const *functions; /* pointer to pointers + to function information */ +}; + +/* Register a new object file module. */ +extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + +#ifndef __COREBOOT__ +/* Called before fork, to avoid double counting. */ +extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; +#endif + +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common value. */ +extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common difference between + consecutive values. */ +extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function that just ors the counters together. */ +extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The profiler functions. */ +extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); +extern void __gcov_pow2_profiler (gcov_type *, gcov_type); +extern void __gcov_one_value_profiler (gcov_type *, gcov_type); +extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *); +extern void __gcov_average_profiler (gcov_type *, gcov_type); +extern void __gcov_ior_profiler (gcov_type *, gcov_type); + +#ifndef inhibit_libc +/* The wrappers around some library functions.. */ +extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; +extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execve (const char *, char *const [], char *const []) + ATTRIBUTE_HIDDEN; +#endif + +#endif /* IN_LIBGCOV */ + +#if IN_LIBGCOV >= 0 + +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var ATTRIBUTE_HIDDEN; + +/* Functions for reading and writing gcov files. In libgcov you can + open the file for reading then writing. Elsewhere you can open the + file either for reading or for writing. When reading a file you may + use the gcov_read_* functions, gcov_sync, gcov_position, & + gcov_error. When writing a file you may use the gcov_write + functions, gcov_seek & gcov_error. When a file is to be rewritten + you use the functions for reading, then gcov_rewrite then the + functions for writing. Your file may become corrupted if you break + these invariants. */ +#if IN_LIBGCOV +GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; +#else +GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); +GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); +#endif +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; + +/* Available everywhere. */ +static gcov_position_t gcov_position (void); +static int gcov_is_error (void); + +GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; + +#if IN_LIBGCOV +/* Available only in libgcov */ +GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, + const struct gcov_summary *) + ATTRIBUTE_HIDDEN; +static void gcov_rewrite (void); +GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; +#else +/* Available outside libgcov */ +GCOV_LINKAGE const char *gcov_read_string (void); +GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, + gcov_unsigned_t /*length */); +#endif + +#if !IN_GCOV +/* Available outside gcov */ +GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +#endif + +#if !IN_GCOV && !IN_LIBGCOV +/* Available only in compiler */ +GCOV_LINKAGE void gcov_write_string (const char *); +GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); +GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); +#endif + +#if IN_GCOV > 0 +/* Available in gcov */ +GCOV_LINKAGE time_t gcov_time (void); +#endif + +/* Save the current position in the gcov file. */ + +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ + +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ + +static inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + +#endif /* IN_LIBGCOV >= 0 */ + +#endif /* GCC_GCOV_IO_H */ diff --git a/src/lib/gcov-iov.h b/src/lib/gcov-iov.h new file mode 100644 index 0000000..09951fb --- /dev/null +++ b/src/lib/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `4.7.2 (4 7) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3430372a) /* 407* */ diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 206e82b..eed243a 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -42,6 +42,7 @@ it with the version available from LANL. #if CONFIG_WRITE_HIGH_TABLES #include #endif +#include #include /** @@ -62,6 +63,10 @@ void hardwaremain(int boot_complete) timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); +#if CONFIG_COVERAGE + coverage_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); diff --git a/src/lib/libgcov.c b/src/lib/libgcov.c new file mode 100644 index 0000000..a32ce55 --- /dev/null +++ b/src/lib/libgcov.c @@ -0,0 +1,1158 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define __COREBOOT__ +#ifdef __COREBOOT__ +#include +#include +#include +#include +typedef s32 pid_t; +#define gcc_assert(x) ASSERT(x) +#define fprintf(file, x...) printk(BIOS_ERR, x) +#define alloca(size) __builtin_alloca (size) +#include "gcov-glue.c" + +/* Define MACROs to be used by coreboot compilation. */ +# define L_gcov +# define L_gcov_interval_profiler +# define L_gcov_pow2_profiler +# define L_gcov_one_value_profiler +# define L_gcov_indirect_call_profiler +# define L_gcov_average_profiler +# define L_gcov_ior_profiler + +# define HAVE_CC_TLS 0 +# define __GCOV_KERNEL__ + +# define IN_LIBGCOV 1 +# define IN_GCOV 0 +#else /* __COREBOOT__ */ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#endif /* __COREBOOT__ */ + +#ifndef __COREBOOT__ +#if defined(inhibit_libc) +#define IN_LIBGCOV (-1) +#else +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include +#define IN_LIBGCOV 1 +#if defined(L_gcov) +#define GCOV_LINKAGE /* nothing */ +#endif +#endif +#endif /* __COREBOOT__ */ +#include "gcov-io.h" + +#if defined(inhibit_libc) +/* If libc and its header files are not available, provide dummy functions. */ + +#ifdef L_gcov +void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} +void __gcov_flush (void) {} +#endif + +#ifdef L_gcov_merge_add +void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_single +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_delta +void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#else + +#ifndef __COREBOOT__ +#include +#if GCOV_LOCKED +#include +#include +#include +#endif +#else +void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif /* __COREBOOT__ */ + +#ifdef L_gcov +#include "gcov-io.c" + +struct gcov_fn_buffer +{ + struct gcov_fn_buffer *next; + unsigned fn_ix; + struct gcov_fn_info info; + /* note gcov_fn_info ends in a trailing array. */ +}; + +/* Chain of per-object gcov structures. */ +static struct gcov_info *gcov_list; + +/* Size of the longest file name. */ +static size_t gcov_max_filename = 0; + +/* Make sure path component of the given FILENAME exists, create + missing directories. FILENAME must be writable. + Returns zero on success, or -1 if an error occurred. */ + +static int +create_file_directory (char *filename) +{ +#ifdef __COREBOOT__ + (void) filename; + return 0; +#else +#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +#else + char *s; + + s = filename; + + if (HAS_DRIVE_SPEC(s)) + s += 2; + if (IS_DIR_SEPARATOR(*s)) + ++s; + for (; *s != '\0'; s++) + if (IS_DIR_SEPARATOR(*s)) + { + char sep = *s; + *s = '\0'; + + /* Try to make directory if it doesn't already exist. */ + if (access (filename, F_OK) == -1 +#ifdef TARGET_POSIX_IO + && mkdir (filename, 0755) == -1 +#else + && mkdir (filename) == -1 +#endif + /* The directory might have been made by another process. */ + && errno != EEXIST) + { + fprintf (stderr, "profiling:%s:Cannot create directory\n", + filename); + *s = sep; + return -1; + }; + + *s = sep; + }; + return 0; +#endif +#endif +} + +static struct gcov_fn_buffer * +free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, + unsigned limit) +{ + struct gcov_fn_buffer *next; + unsigned ix, n_ctr = 0; + + if (!buffer) + return 0; + next = buffer->next; + + for (ix = 0; ix != limit; ix++) + if (gi_ptr->merge[ix]) + free (buffer->info.ctrs[n_ctr++].values); + free (buffer); + return next; +} + +static struct gcov_fn_buffer ** +buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, + struct gcov_fn_buffer **end_ptr, unsigned fn_ix) +{ + unsigned n_ctrs = 0, ix = 0; + struct gcov_fn_buffer *fn_buffer; + unsigned len; + + for (ix = GCOV_COUNTERS; ix--;) + if (gi_ptr->merge[ix]) + n_ctrs++; + + len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; + fn_buffer = (struct gcov_fn_buffer *)malloc (len); + + if (!fn_buffer) + goto fail; + + fn_buffer->next = 0; + fn_buffer->fn_ix = fn_ix; + fn_buffer->info.ident = gcov_read_unsigned (); + fn_buffer->info.lineno_checksum = gcov_read_unsigned (); + fn_buffer->info.cfg_checksum = gcov_read_unsigned (); + + for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) + { + gcov_unsigned_t length; + gcov_type *values; + + if (!gi_ptr->merge[ix]) + continue; + + if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) + { + len = 0; + goto fail; + } + + length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); + len = length * sizeof (gcov_type); + values = (gcov_type *)malloc (len); + if (!values) + goto fail; + + fn_buffer->info.ctrs[n_ctrs].num = length; + fn_buffer->info.ctrs[n_ctrs].values = values; + + while (length--) + *values++ = gcov_read_counter (); + n_ctrs++; + } + + *end_ptr = fn_buffer; + return &fn_buffer->next; + +fail: + fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix, + len ? "cannot allocate" : "counter mismatch", len ? len : ix); + + return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); +} + +/* Add an unsigned value to the current crc */ + +static gcov_unsigned_t +crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) +{ + unsigned ix; + + for (ix = 32; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; + crc32 <<= 1; + crc32 ^= feedback; + } + + return crc32; +} + +/* Check if VERSION of the info block PTR matches libgcov one. + Return 1 on success, or zero in case of versions mismatch. + If FILENAME is not NULL, its value used for reporting purposes + instead of value from the info block. */ + +static int +gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, + const char *filename) +{ + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fprintf (stderr, + "profiling:%s:Version mismatch - expected %.4s got %.4s\n", + filename? filename : ptr->filename, e, v); + return 0; + } + return 1; +} + +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. We use this + program's checksum to make sure we only accumulate whole program + statistics to the correct summary. An object file might be embedded + in two separate programs, and we must keep the two program + summaries separate. */ + +static void +gcov_exit (void) +{ + struct gcov_info *gi_ptr; + const struct gcov_fn_info *gfi_ptr; + struct gcov_summary this_prg; /* summary for program. */ + struct gcov_summary all_prg; /* summary for all instances of program. */ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; + int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; + size_t prefix_length; + char *gi_filename, *gi_filename_up; + gcov_unsigned_t crc32 = 0; + + memset (&all_prg, 0, sizeof (all_prg)); + /* Find the totals for this execution. */ + memset (&this_prg, 0, sizeof (this_prg)); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); + crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); + + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (gfi_ptr && gfi_ptr->key != gi_ptr) + gfi_ptr = 0; + + crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); + crc32 = crc32_unsigned (crc32, + gfi_ptr ? gfi_ptr->lineno_checksum : 0); + if (!gfi_ptr) + continue; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + cs_ptr = &this_prg.ctrs[t_ix]; + cs_ptr->num += ci_ptr->num; + crc32 = crc32_unsigned (crc32, ci_ptr->num); + + for (c_num = 0; c_num < ci_ptr->num; c_num++) + { + cs_ptr->sum_all += ci_ptr->values[c_num]; + if (cs_ptr->run_max < ci_ptr->values[c_num]) + cs_ptr->run_max = ci_ptr->values[c_num]; + } + ci_ptr++; + } + } + } + +#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); + if (tmp) + { + gcov_prefix_strip = atoi (tmp); + /* Do not consider negative values. */ + if (gcov_prefix_strip < 0) + gcov_prefix_strip = 0; + } + } + + /* Get file name relocation prefix. Non-absolute values are ignored. */ + gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix) + { + prefix_length = strlen(gcov_prefix); + + /* Remove an unnecessary trailing '/' */ + if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; + } + else +#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume + relative. */ + if (gcov_prefix_strip != 0 && prefix_length == 0) + { + gcov_prefix = "."; + prefix_length = 1; + } + /* Allocate and initialize the filename scratch space plus one. */ + gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); + if (prefix_length) + memcpy (gi_filename, gcov_prefix, prefix_length); + gi_filename_up = gi_filename + prefix_length; + + /* Now merge each file. */ + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned n_counts; + struct gcov_summary prg; /* summary for this object over all + program. */ + struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all; + int error = 0; + gcov_unsigned_t tag, length; + gcov_position_t summary_pos = 0; + gcov_position_t eof_pos = 0; + const char *fname, *s; + struct gcov_fn_buffer *fn_buffer = 0; + struct gcov_fn_buffer **fn_tail = &fn_buffer; + + fname = gi_ptr->filename; + + /* Avoid to add multiple drive letters into combined path. */ + if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) + fname += 2; + + /* Build relocated filename, stripping off leading + directories from the initial filename if requested. */ + if (gcov_prefix_strip > 0) + { + int level = 0; + s = fname; + if (IS_DIR_SEPARATOR(*s)) + ++s; + + /* Skip selected directory levels. */ + for (; (*s != '\0') && (level < gcov_prefix_strip); s++) + if (IS_DIR_SEPARATOR(*s)) + { + fname = s; + level++; + } + } + + /* Update complete filename with stripped original. */ + if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + { + /* If prefix is given, add directory separator. */ + strcpy (gi_filename_up, "/"); + strcpy (gi_filename_up + 1, fname); + } + else + strcpy (gi_filename_up, fname); + + if (!gcov_open (gi_filename)) + { + /* Open failed likely due to missed directory. + Create directory and retry to open file. */ + if (create_file_directory (gi_filename)) + { + fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + continue; + } + if (!gcov_open (gi_filename)) + { + fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + continue; + } + } + + tag = gcov_read_unsigned (); + if (tag) + { + /* Merge data from file. */ + if (tag != GCOV_DATA_MAGIC) + { + fprintf (stderr, "profiling:%s:Not a gcov data file\n", + gi_filename); + goto read_fatal; + } + length = gcov_read_unsigned (); + if (!gcov_version (gi_ptr, length, gi_filename)) + goto read_fatal; + + length = gcov_read_unsigned (); + if (length != gi_ptr->stamp) + /* Read from a different compilation. Overwrite the file. */ + goto rewrite; + + /* Look for program summary. */ + for (f_ix = 0;;) + { + struct gcov_summary tmp; + + eof_pos = gcov_position (); + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_PROGRAM_SUMMARY) + break; + + f_ix--; + length = gcov_read_unsigned (); + if (length != GCOV_TAG_SUMMARY_LENGTH) + goto read_mismatch; + gcov_read_summary (&tmp); + if ((error = gcov_is_error ())) + goto read_error; + if (summary_pos || tmp.checksum != crc32) + goto next_summary; + + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num) + goto next_summary; + prg = tmp; + summary_pos = eof_pos; + + next_summary:; + } + + /* Merge execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; + f_ix++, tag = gcov_read_unsigned ()) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (tag != GCOV_TAG_FUNCTION) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (!length) + /* This function did not appear in the other program. + We have nothing to merge. */ + continue; + + if (length != GCOV_TAG_FUNCTION_LENGTH) + goto read_mismatch; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + { + /* This function appears in the other program. We + need to buffer the information in order to write + it back out -- we'll be inserting data before + this point, so cannot simply keep the data in the + file. */ + fn_tail = buffer_fn_data (gi_filename, + gi_ptr, fn_tail, f_ix); + if (!fn_tail) + goto read_mismatch; + continue; + } + + length = gcov_read_unsigned (); + if (length != gfi_ptr->ident) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->lineno_checksum) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->cfg_checksum) + goto read_mismatch; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + gcov_merge_fn merge = gi_ptr->merge[t_ix]; + + if (!merge) + continue; + + tag = gcov_read_unsigned (); + length = gcov_read_unsigned (); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) + goto read_mismatch; + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } + if ((error = gcov_is_error ())) + goto read_error; + } + + if (tag) + { + read_mismatch:; + fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n", + gi_filename, f_ix >= 0 ? "function" : "summary", + f_ix < 0 ? -1 - f_ix : f_ix); + goto read_fatal; + } + } + goto rewrite; + + read_error:; + fprintf (stderr, "profiling:%s:%s merging\n", gi_filename, + error < 0 ? "Overflow": "Error"); + + goto read_fatal; + + rewrite:; + gcov_rewrite (); + if (!summary_pos) + { + memset (&prg, 0, sizeof (prg)); + summary_pos = eof_pos; + } + + /* Merge the summaries. */ + for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) + { + cs_prg = &prg.ctrs[t_ix]; + cs_tprg = &this_prg.ctrs[t_ix]; + cs_all = &all_prg.ctrs[t_ix]; + + if (gi_ptr->merge[t_ix]) + { + if (!cs_prg->runs++) + cs_prg->num = cs_tprg->num; + cs_prg->sum_all += cs_tprg->sum_all; + if (cs_prg->run_max < cs_tprg->run_max) + cs_prg->run_max = cs_tprg->run_max; + cs_prg->sum_max += cs_tprg->run_max; + } + else if (cs_prg->runs) + goto read_mismatch; + + if (!cs_all->runs && cs_prg->runs) + memcpy (cs_all, cs_prg, sizeof (*cs_all)); + else if (!all_prg.checksum + && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) + && memcmp (cs_all, cs_prg, sizeof (*cs_all))) + { + fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n", + gi_filename, GCOV_LOCKED + ? "" : " or concurrently updated without locking support"); + all_prg.checksum = ~0u; + } + } + + prg.checksum = crc32; + + /* Write out the data. */ + if (!eof_pos) + { + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); + } + + if (summary_pos) + gcov_seek (summary_pos); + + /* Generate whole program statistics. */ + gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg); + + if (summary_pos < eof_pos) + gcov_seek (eof_pos); + + /* Write execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + unsigned buffered = 0; + + if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix) + { + /* Buffered data from another program. */ + buffered = 1; + gfi_ptr = &fn_buffer->info; + length = GCOV_TAG_FUNCTION_LENGTH; + } + else + { + gfi_ptr = gi_ptr->functions[f_ix]; + if (gfi_ptr && gfi_ptr->key == gi_ptr) + length = GCOV_TAG_FUNCTION_LENGTH; + else + length = 0; + } + + gcov_write_tag_length (GCOV_TAG_FUNCTION, length); + if (!length) + continue; + + gcov_write_unsigned (gfi_ptr->ident); + gcov_write_unsigned (gfi_ptr->lineno_checksum); + gcov_write_unsigned (gfi_ptr->cfg_checksum); + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + n_counts = ci_ptr->num; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + gcov_type *c_ptr = ci_ptr->values; + while (n_counts--) + gcov_write_counter (*c_ptr++); + ci_ptr++; + } + if (buffered) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + } + + gcov_write_unsigned (0); + + read_fatal:; + while (fn_buffer) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + + if ((error = gcov_close ())) + fprintf (stderr, error < 0 ? + "profiling:%s:Overflow writing\n" : + "profiling:%s:Error writing\n", + gi_filename); + } +} + +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + +void +__gcov_init (struct gcov_info *info) +{ + if (!info->version || !info->n_functions) + return; + if (gcov_version (info, info->version, 0)) + { + size_t filename_length = strlen(info->filename); + + /* Refresh the longest file name information */ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + +#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); +#endif + + info->next = gcov_list; + gcov_list = info; + } + info->version = 0; +} + +/* Called before fork or exec - write out profile information gathered so + far and reset it to zero. This avoids duplication or loss of the + profile information gathered so far. */ + +void +__gcov_flush (void) +{ + const struct gcov_info *gi_ptr; + + gcov_exit (); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + +#endif /* L_gcov */ + +#ifdef L_gcov_merge_add +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_add (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters += gcov_read_counter (); +} +#endif /* L_gcov_merge_add */ + +#ifdef L_gcov_merge_ior +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_ior (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters |= gcov_read_counter (); +} +#endif + +#ifdef L_gcov_merge_single +/* The profile merging function for choosing the most common value. + * It is given an array COUNTERS of N_COUNTERS old counters and it + * reads the same number of counters from the gcov file. The counters + * are split into 3-tuples where the members of the tuple have + * meanings: + * + * -- the stored candidate on the most common value of the measured entity + * -- counter + * -- total number of evaluations of the value + */ +void +__gcov_merge_single (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 3)); + n_measures = n_counters / 3; + for (i = 0; i < n_measures; i++, counters += 3) + { + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[0] == value) + counters[1] += counter; + else if (counter > counters[1]) + { + counters[0] = value; + counters[1] = counter - counters[1]; + } + else + counters[1] -= counter; + counters[2] += all; + } +} +#endif /* L_gcov_merge_single */ + +#ifdef L_gcov_merge_delta +/* The profile merging function for choosing the most common + difference between two consecutive evaluations of the value. It is + given an array COUNTERS of N_COUNTERS old counters and it reads the + same number of counters from the gcov file. The counters are split + into 4-tuples where the members of the tuple have meanings: + + -- the last value of the measured entity + -- the stored candidate on the most common difference + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_delta (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 4)); + n_measures = n_counters / 4; + for (i = 0; i < n_measures; i++, counters += 4) + { + /* last = */ gcov_read_counter (); + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[1] == value) + counters[2] += counter; + else if (counter > counters[2]) + { + counters[1] = value; + counters[2] = counter - counters[2]; + } + else + counters[2] -= counter; + counters[3] += all; + } +} +#endif /* L_gcov_merge_delta */ + +#ifdef L_gcov_interval_profiler +/* If VALUE is in interval , then increases the + corresponding counter in COUNTERS. If the VALUE is above or below + the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased + instead. */ + +void +__gcov_interval_profiler (gcov_type *counters, gcov_type value, + int start, unsigned steps) +{ + gcov_type delta = value - start; + if (delta < 0) + counters[steps + 1]++; + else if (delta >= steps) + counters[steps]++; + else + counters[delta]++; +} +#endif + +#ifdef L_gcov_pow2_profiler +/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise + COUNTERS[0] is incremented. */ + +void +__gcov_pow2_profiler (gcov_type *counters, gcov_type value) +{ + if (value & (value - 1)) + counters[0]++; + else + counters[1]++; +} +#endif + +/* Tries to determine the most common value among its inputs. Checks if the + value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] + is incremented. If this is not the case and COUNTERS[1] is not zero, + COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and + VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this + function is called more than 50% of the time with one value, this value + will be in COUNTERS[0] in the end. + + In any case, COUNTERS[2] is incremented. */ + +static inline void +__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) +{ + if (value == counters[0]) + counters[1]++; + else if (counters[1] == 0) + { + counters[1] = 1; + counters[0] = value; + } + else + counters[1]--; + counters[2]++; +} + +#ifdef L_gcov_one_value_profiler +void +__gcov_one_value_profiler (gcov_type *counters, gcov_type value) +{ + __gcov_one_value_profiler_body (counters, value); +} +#endif + +#ifdef L_gcov_indirect_call_profiler + +/* By default, the C++ compiler will use function addresses in the + vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero + tells the compiler to use function descriptors instead. The value + of this macro says how many words wide the descriptor is (normally 2), + but it may be dependent on target flags. Since we do not have access + to the target flags here we just check to see if it is set and use + that to set VTABLE_USES_DESCRIPTORS to 0 or 1. + + It is assumed that the address of a function descriptor may be treated + as a pointer to a function. */ + +#ifdef TARGET_VTABLE_USES_DESCRIPTORS +#define VTABLE_USES_DESCRIPTORS 1 +#else +#define VTABLE_USES_DESCRIPTORS 0 +#endif + +/* Tries to determine the most common value among its inputs. */ +void +__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, + void* cur_func, void* callee_func) +{ + /* If the C++ virtual tables contain function descriptors then one + function may have multiple descriptors and we need to dereference + the descriptors to see if they point to the same function. */ + if (cur_func == callee_func + || (VTABLE_USES_DESCRIPTORS && callee_func + && *(void **) cur_func == *(void **) callee_func)) + __gcov_one_value_profiler_body (counter, value); +} +#endif + + +#ifdef L_gcov_average_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_average_profiler (gcov_type *counters, gcov_type value) +{ + counters[0] += value; + counters[1] ++; +} +#endif + +#ifdef L_gcov_ior_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_ior_profiler (gcov_type *counters, gcov_type value) +{ + *counters |= value; +} +#endif + +#ifdef L_gcov_fork +/* A wrapper for the fork function. Flushes the accumulated profiling data, so + that they are not counted twice. */ + +pid_t +__gcov_fork (void) +{ + __gcov_flush (); + return fork (); +} +#endif + +#ifdef L_gcov_execl +/* A wrapper for the execl function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execl (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execv (path, args); +} +#endif + +#ifdef L_gcov_execlp +/* A wrapper for the execlp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execlp (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execvp (path, args); +} +#endif + +#ifdef L_gcov_execle +/* A wrapper for the execle function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execle (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + char **envp; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + envp = va_arg (aq, char **); + va_end (aq); + + return execve (path, args, envp); +} +#endif + +#ifdef L_gcov_execv +/* A wrapper for the execv function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execv (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execv (path, argv); +} +#endif + +#ifdef L_gcov_execvp +/* A wrapper for the execvp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execvp (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execvp (path, argv); +} +#endif + +#ifdef L_gcov_execve +/* A wrapper for the execve function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execve (const char *path, char *const argv[], char *const envp[]) +{ + __gcov_flush (); + return execve (path, argv, envp); +} +#endif +#endif /* inhibit_libc */ diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 2556a14..c5fb62a 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -32,6 +32,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR @@ -518,6 +519,9 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) #if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); #endif +#if CONFIG_COVERAGE + coverage_exit(); +#endif /* Before we go off to run the payload, see if * we stayed within our bounds. diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index a777a8f..bc6bd6b 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define MAP_BYTES (1024*1024) @@ -82,7 +84,7 @@ static void *map_memory(u64 physical) /* Mapped memory must be aligned to page size */ p = physical & ~(page - 1); - debug("Mapping 1MB of physical memory at %zx.\n", p); + debug("Mapping 1MB of physical memory at 0x%zx.\n", p); v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); @@ -103,8 +105,13 @@ static void *map_memory(u64 physical) static void unmap_memory(void) { + if (mapped_virtual == NULL) { + fprintf(stderr, "Error unmapping memory\n"); + return; + } debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); munmap(mapped_virtual, MAP_BYTES); + mapped_virtual = NULL; } /* @@ -347,7 +354,7 @@ struct cbmem_entry { uint64_t size; }; -void dump_cbmem_toc(void) +static void dump_cbmem_toc(void) { int i; uint64_t start; @@ -374,7 +381,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_GDT: printf("GDT "); break; case CBMEM_ID_ACPI: printf("ACPI "); break; case CBMEM_ID_ACPI_GNVS: printf("ACPI GNVS "); break; - case CBMEM_ID_CBTABLE: printf("COREBOOTE "); break; + case CBMEM_ID_CBTABLE: printf("COREBOOT "); break; case CBMEM_ID_PIRQ: printf("IRQ TABLE "); break; case CBMEM_ID_MPTABLE: printf("SMP TABLE "); break; case CBMEM_ID_RESUME: printf("ACPI RESUME "); break; @@ -384,6 +391,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_MRCDATA: printf("MRC DATA "); break; case CBMEM_ID_CONSOLE: printf("CONSOLE "); break; case CBMEM_ID_ELOG: printf("ELOG "); break; + case CBMEM_ID_COVERAGE: printf("COVERAGE "); break; default: printf("%08x ", entries[i].id); break; } @@ -393,7 +401,111 @@ void dump_cbmem_toc(void) unmap_memory(); } -void print_version(void) +#define COVERAGE_MAGIC 0x584d4153 +struct file { + uint32_t magic; + uint32_t next; + uint32_t filename; + uint32_t data; + int offset; + int len; +}; + +static int mkpath(char *path, mode_t mode) +{ + assert (path && *path); + char *p; + for (p = strchr(path+1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) { + *p = '/'; + return -1; + } + } + *p = '/'; + } + return 0; +} + +static void dump_coverage(void) +{ + int i, found = 0; + uint64_t start; + struct cbmem_entry *entries; + void *coverage; + unsigned long phys_offset; +#define phys_to_virt(x) ((void *)(unsigned long)(x) + phys_offset) + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + for (i=0; imagic == COVERAGE_MAGIC) { + FILE *f; + char *filename; + + debug(" -> %s\n", (char *)phys_to_virt(file->filename)); + filename = strdup((char *)phys_to_virt(file->filename)); + if (mkpath(filename, 0755) == -1) { + perror("Directory for coverage data could " + "not be created"); + exit(1); + } + f = fopen(filename, "wb"); + if (!f) { + printf("Could not open %s: %s\n", + filename, strerror(errno)); + exit(1); + } + if (fwrite((void *)phys_to_virt(file->data), + file->len, 1, f) != 1) { + printf("Could not write to %s: %s\n", + filename, strerror(errno)); + exit(1); + } + fclose(f); + free(filename); + + if (file->next) + file = (struct file *)phys_to_virt(file->next); + else + file = NULL; + } + unmap_memory(); +} + +static void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); printf("Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.\n\n"); @@ -409,11 +521,12 @@ void print_version(void) "along with this program. If not, see .\n\n"); } -void print_usage(const char *name) +static void print_usage(const char *name) { - printf("usage: %s [-vh?]\n", name); + printf("usage: %s [-cCltVvh?]\n", name); printf("\n" " -c | --console: print cbmem console\n" + " -C | --coverage: dump coverage information\n" " -l | --list: print cbmem table of contents\n" " -t | --timestamps: print timestamp information\n" " -V | --verbose: verbose (debugging) output\n" @@ -430,12 +543,14 @@ int main(int argc, char** argv) int print_defaults = 1; int print_console = 0; + int print_coverage = 0; int print_list = 0; int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { {"console", 0, 0, 'c'}, + {"coverage", 0, 0, 'C'}, {"list", 0, 0, 'l'}, {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, @@ -443,13 +558,17 @@ int main(int argc, char** argv) {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cltVvh?", + while ((opt = getopt_long(argc, argv, "cCltVvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': print_console = 1; print_defaults = 0; break; + case 'C': + print_coverage = 1; + print_defaults = 0; + break; case 'l': print_list = 1; print_defaults = 0; @@ -490,6 +609,9 @@ int main(int argc, char** argv) if (print_console) dump_console(); + if (print_coverage) + dump_coverage(); + if (print_list) dump_cbmem_toc(); From gerrit at coreboot.org Wed Jan 9 01:32:09 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Wed, 9 Jan 2013 01:32:09 +0100 Subject: [coreboot] Patch set updated for coreboot: fa280c2 Implement GCC code coverage analysis References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2052 -gerrit commit fa280c22fda09a3678edc1bd2be3ffc05da43ff4 Author: Stefan Reinauer Date: Tue Dec 18 16:23:28 2012 -0800 Implement GCC code coverage analysis In order to provide some insight on what code is executed during coreboot's run time and how well our test scenarios work, this adds code coverage support to coreboot's ram stage. This should be easily adaptable for payloads, and maybe even romstage. See http://gcc.gnu.org/onlinedocs/gcc/Gcov.html for more information. To instrument coreboot, select CONFIG_COVERAGE ("Code coverage support") in Kconfig, and recompile coreboot. coreboot will then store its code coverage information into CBMEM, if possible. Then, run "cbmem -CV" as root on the target system running the instrumented coreboot binary. This will create a whole bunch of .gcda files that contain coverage information. Tar them up, copy them to your build system machine, and untar them. Then you can use your favorite coverage utility (gcov, lcov, ...) to visualize code coverage. For a sneak peak of what will expect you, please take a look at http://www.coreboot.org/~stepan/coreboot-coverage/ Change-Id: Ib287d8309878a1f5c4be770c38b1bc0bb3aa6ec7 Signed-off-by: Stefan Reinauer --- Makefile.inc | 3 + src/Kconfig | 18 + src/arch/armv7/Makefile.inc | 2 +- src/arch/armv7/coreboot_ram.ld | 8 + src/arch/x86/Makefile.inc | 2 +- src/arch/x86/boot/acpi.c | 4 + src/arch/x86/coreboot_ram.ld | 8 + src/include/cbmem.h | 1 + src/include/coverage.h | 21 + src/lib/Makefile.inc | 1 + src/lib/cbmem.c | 2 + src/lib/gcov-glue.c | 153 ++++++ src/lib/gcov-io.c | 556 +++++++++++++++++++ src/lib/gcov-io.h | 639 ++++++++++++++++++++++ src/lib/gcov-iov.h | 4 + src/lib/hardwaremain.c | 5 + src/lib/libgcov.c | 1158 ++++++++++++++++++++++++++++++++++++++++ src/lib/selfboot.c | 4 + util/cbmem/cbmem.c | 136 ++++- 19 files changed, 2716 insertions(+), 9 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index a066e25..3731797 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,6 +99,9 @@ romstage-S-ccopts:=-D__PRE_RAM__ ifeq ($(CONFIG_TRACE),y) ramstage-c-ccopts:= -finstrument-functions endif +ifeq ($(CONFIG_COVERAGE),y) +ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) diff --git a/src/Kconfig b/src/Kconfig index 0a94ed8..2c97327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,15 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail. +config COVERAGE + bool "Code coverage support" + depends on COMPILER_GCC + default n + help + Add code coverage support for coreboot. This will store code + coverage information in CBMEM for extraction from user space. + If unsure, say N. + endmenu source src/mainboard/Kconfig @@ -868,6 +877,15 @@ config TRACE the 0xaaaabbbb is the actual function and 0xccccdddd is EIP of calling function. Please note some printk releated functions are omitted from trace to have good looking console dumps. + +config DEBUG_COVERAGE + bool "Debug code coverage" + default n + depends on COVERAGE + help + If enabled, the code coverage hooks in coreboot will output some + information about the coverage data that is dumped. + endmenu # These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..4a836d1 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -121,7 +121,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m -m armelf_linux_eabi -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --wrap __uidiv --wrap __do_div64 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/armv7/coreboot_ram.ld b/src/arch/armv7/coreboot_ram.ld index 57ddd03..329bce4 100644 --- a/src/arch/armv7/coreboot_ram.ld +++ b/src/arch/armv7/coreboot_ram.ld @@ -38,6 +38,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index e84700e..ea86f8f 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -166,7 +166,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 1d7dbf8..730e53e 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -36,6 +36,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -642,6 +643,9 @@ void suspend_resume(void) /* Call mainboard resume handler first, if defined. */ if (mainboard_suspend_resume) mainboard_suspend_resume(); +#if CONFIG_COVERAGE + coverage_exit(); +#endif post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); } diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld index a87a0e7..7ce0367 100644 --- a/src/arch/x86/coreboot_ram.ld +++ b/src/arch/x86/coreboot_ram.ld @@ -39,6 +39,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 21efe77..08e913a 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -55,6 +55,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_COVERAGE 0x47434f56 #define CBMEM_ID_NONE 0x00000000 #ifndef __ASSEMBLER__ diff --git a/src/include/coverage.h b/src/include/coverage.h new file mode 100644 index 0000000..e1c50c5 --- /dev/null +++ b/src/include/coverage.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void coverage_init(void); +void coverage_exit(void); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6b3f0d8..6796448 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -70,6 +70,7 @@ ramstage-$(CONFIG_USBDEBUG) += usbdebug.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index 7378d8c..f270f5d 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -260,6 +260,8 @@ void cbmem_list(void) case CBMEM_ID_TIMESTAMP: printk(BIOS_DEBUG, "TIME STAMP "); break; case CBMEM_ID_MRCDATA: printk(BIOS_DEBUG, "MRC DATA "); break; case CBMEM_ID_CONSOLE: printk(BIOS_DEBUG, "CONSOLE "); break; + case CBMEM_ID_ELOG: printk(BIOS_DEBUG, "ELOG "); break; + case CBMEM_ID_COVERAGE: printk(BIOS_DEBUG, "COVERAGE "); break; default: printk(BIOS_DEBUG, "%08x ", cbmem_toc[i].id); } printk(BIOS_DEBUG, "%08llx ", cbmem_toc[i].base); diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c new file mode 100644 index 0000000..7c069cb --- /dev/null +++ b/src/lib/gcov-glue.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +typedef struct file { + uint32_t magic; + struct file *next; + char *filename; + char *data; + int offset; + int len; +} FILE; + +#define SEEK_SET 0 /* Seek from beginning of file. */ + +#define DIR_SEPARATOR '/' +#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#define HAS_DRIVE_SPEC(f) (0) + +#define COVERAGE_SIZE (32*1024) + +static FILE *current_file = NULL; +static FILE *previous_file = NULL; + +static FILE *fopen(const char *path, const char *mode) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fopen %s with mode %s\n", + path, mode); +#endif + if (!current_file) { + current_file = cbmem_add(CBMEM_ID_COVERAGE, 32*1024); + } else { + previous_file = current_file; + current_file = (FILE *)(ALIGN(((unsigned long)previous_file->data + previous_file->len), 16)); + } + + // TODO check if we're at the end of the CBMEM region (ENOMEM) + if (current_file) { + current_file->magic = 0x584d4153; + current_file->next = NULL; + if (previous_file) + previous_file->next = current_file; + current_file->filename = (char *)¤t_file[1]; + strcpy(current_file->filename, path); + current_file->data = (char *)ALIGN(((unsigned long)current_file->filename + strlen(path) + 1), 16); + current_file->offset = 0; + current_file->len = 0; + } + + return current_file; +} + +static int fclose(FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fclose %s\n", stream->filename); +#endif + return 0; +} + +static int fseek(FILE *stream, long offset, int whence) +{ + /* fseek should only be called with offset==0 and whence==SEEK_SET + * to a freshly opened file. */ + gcc_assert (offset == 0 && whence == SEEK_SET); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fseek %s offset=%d whence=%d\n", + stream->filename, offset, whence); +#endif + return 0; +} + +static long ftell(FILE *stream) +{ + /* ftell should currently not be called */ + gcc_assert(0); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "ftell %s\n", stream->filename); +#endif + return 0; +} + +static size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fread: ptr=%p size=%zd nmemb=%zd FILE*=%p\n", + ptr, size, nmemb, stream); +#endif + return 0; +} + +static size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fwrite: %zd * 0x%zd bytes to file %s\n", + nmemb, size, stream->filename); +#endif + // TODO check if file is last opened file and fail otherwise. + + memcpy(stream->data + stream->offset, ptr, size * nmemb); + stream->len += (nmemb * size) - (stream->len - stream->offset); + stream->offset += nmemb * size; + return nmemb; +} + +static void setbuf(FILE *stream, char *buf) +{ + gcc_assert(buf == 0); +} + +void coverage_init(void) +{ + extern long __CTOR_LIST__; + typedef void (*func_ptr)(void) ; + func_ptr *ctor = (func_ptr*) &__CTOR_LIST__; + if (ctor == NULL) + return; + + for ( ; *ctor != (func_ptr) 0; ctor++) { + (*ctor)(); + } +} + +void __gcov_flush(void); +void coverage_exit(void) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "Syncing coverage data.\n"); +#endif + __gcov_flush(); +} + + diff --git a/src/lib/gcov-io.c b/src/lib/gcov-io.c new file mode 100644 index 0000000..d2fee03 --- /dev/null +++ b/src/lib/gcov-io.c @@ -0,0 +1,556 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007, + 2008 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Routines declared in gcov-io.h. This file should be #included by + another source file, after having #included gcov-io.h. */ + +#ifdef __COREBOOT__ + +#endif + +#if !IN_GCOV +static void gcov_write_block (unsigned); +static gcov_unsigned_t *gcov_write_words (unsigned); +#endif +static const gcov_unsigned_t *gcov_read_words (unsigned); +#if !IN_LIBGCOV +static void gcov_allocate (unsigned); +#endif + +static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +{ +#if !IN_LIBGCOV + if (gcov_var.endian) + { + value = (value >> 16) | (value << 16); + value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); + } +#endif + return value; +} + +/* Open a gcov file. NAME is the name of the file to open and MODE + indicates whether a new file should be created, or an existing file + opened. If MODE is >= 0 an existing file will be opened, if + possible, and if MODE is <= 0, a new file will be created. Use + MODE=0 to attempt to reopen an existing file and then fall back on + creating a new one. If MODE < 0, the file will be opened in + read-only mode. Otherwise it will be opened for modification. + Return zero on failure, >0 on opening an existing file and <0 on + creating a new one. */ + +GCOV_LINKAGE int +#if IN_LIBGCOV +gcov_open (const char *name) +#else +gcov_open (const char *name, int mode) +#endif +{ +#if IN_LIBGCOV + const int mode = 0; +#endif +#if GCOV_LOCKED + struct flock s_flock; + int fd; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif + + gcc_assert (!gcov_var.file); + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; +#if !IN_LIBGCOV + gcov_var.endian = 0; +#endif +#if GCOV_LOCKED + if (mode > 0) + { + /* Read-only mode - acquire a read-lock. */ + s_flock.l_type = F_RDLCK; + fd = open (name, O_RDONLY); + } + else + { + /* Write mode - acquire a write-lock. */ + s_flock.l_type = F_WRLCK; + fd = open (name, O_RDWR | O_CREAT, 0666); + } + if (fd < 0) + return 0; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; + + gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); + + if (!gcov_var.file) + { + close (fd); + return 0; + } + + if (mode > 0) + gcov_var.mode = 1; + else if (mode == 0) + { + struct stat st; + + if (fstat (fd, &st) < 0) + { + fclose (gcov_var.file); + gcov_var.file = 0; + return 0; + } + if (st.st_size != 0) + gcov_var.mode = 1; + else + gcov_var.mode = mode * 2 + 1; + } + else + gcov_var.mode = mode * 2 + 1; +#else + if (mode >= 0) + gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + + if (gcov_var.file) + gcov_var.mode = 1; + else if (mode <= 0) + { + gcov_var.file = fopen (name, "w+b"); + if (gcov_var.file) + gcov_var.mode = mode * 2 + 1; + } + if (!gcov_var.file) + return 0; +#endif + + setbuf (gcov_var.file, (char *)0); + + return 1; +} + +/* Close the current gcov file. Flushes data to disk. Returns nonzero + on failure or error flag set. */ + +GCOV_LINKAGE int +gcov_close (void) +{ + if (gcov_var.file) + { +#if !IN_GCOV + if (gcov_var.offset && gcov_var.mode < 0) + gcov_write_block (gcov_var.offset); +#endif + fclose (gcov_var.file); + gcov_var.file = 0; + gcov_var.length = 0; + } +#if !IN_LIBGCOV + free (gcov_var.buffer); + gcov_var.alloc = 0; + gcov_var.buffer = 0; +#endif + gcov_var.mode = 0; + return gcov_var.error; +} + +#if !IN_LIBGCOV +/* Check if MAGIC is EXPECTED. Use it to determine endianness of the + file. Returns +1 for same endian, -1 for other endian and zero for + not EXPECTED. */ + +GCOV_LINKAGE int +gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) +{ + if (magic == expected) + return 1; + magic = (magic >> 16) | (magic << 16); + magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); + if (magic == expected) + { + gcov_var.endian = 1; + return -1; + } + return 0; +} +#endif + +#if !IN_LIBGCOV +static void +gcov_allocate (unsigned length) +{ + size_t new_size = gcov_var.alloc; + + if (!new_size) + new_size = GCOV_BLOCK_SIZE; + new_size += length; + new_size *= 2; + + gcov_var.alloc = new_size; + gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); +} +#endif + +#if !IN_GCOV +/* Write out the current block, if needs be. */ + +static void +gcov_write_block (unsigned size) +{ + if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + gcov_var.error = 1; + gcov_var.start += size; + gcov_var.offset -= size; +} + +/* Allocate space to write BYTES bytes to the gcov file. Return a + pointer to those bytes, or NULL on failure. */ + +static gcov_unsigned_t * +gcov_write_words (unsigned words) +{ + gcov_unsigned_t *result; + + gcc_assert (gcov_var.mode < 0); +#if IN_LIBGCOV + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + { + gcov_write_block (GCOV_BLOCK_SIZE); + if (gcov_var.offset) + { + gcc_assert (gcov_var.offset == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); + } + } +#else + if (gcov_var.offset + words > gcov_var.alloc) + gcov_allocate (gcov_var.offset + words); +#endif + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + + return result; +} + +/* Write unsigned VALUE to coverage file. Sets error flag + appropriately. */ + +GCOV_LINKAGE void +gcov_write_unsigned (gcov_unsigned_t value) +{ + gcov_unsigned_t *buffer = gcov_write_words (1); + + buffer[0] = value; +} + +/* Write counter VALUE to coverage file. Sets error flag + appropriately. */ + +#if IN_LIBGCOV +GCOV_LINKAGE void +gcov_write_counter (gcov_type value) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = (gcov_unsigned_t) value; + if (sizeof (value) > sizeof (gcov_unsigned_t)) + buffer[1] = (gcov_unsigned_t) (value >> 32); + else + buffer[1] = 0; +} +#endif /* IN_LIBGCOV */ + +#if !IN_LIBGCOV +/* Write STRING to coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE void +gcov_write_string (const char *string) +{ + unsigned length = 0; + unsigned alloc = 0; + gcov_unsigned_t *buffer; + + if (string) + { + length = strlen (string); + alloc = (length + 4) >> 2; + } + + buffer = gcov_write_words (1 + alloc); + + buffer[0] = alloc; + buffer[alloc] = 0; + memcpy (&buffer[1], string, length); +} +#endif + +#if !IN_LIBGCOV +/* Write a tag TAG and reserve space for the record length. Return a + value to be used for gcov_write_length. */ + +GCOV_LINKAGE gcov_position_t +gcov_write_tag (gcov_unsigned_t tag) +{ + gcov_position_t result = gcov_var.start + gcov_var.offset; + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = 0; + + return result; +} + +/* Write a record length using POSITION, which was returned by + gcov_write_tag. The current file position is the end of the + record, and is restored before returning. Returns nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_length (gcov_position_t position) +{ + unsigned offset; + gcov_unsigned_t length; + gcov_unsigned_t *buffer; + + gcc_assert (gcov_var.mode < 0); + gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); + gcc_assert (position >= gcov_var.start); + offset = position - gcov_var.start; + length = gcov_var.offset - offset - 2; + buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; + buffer[1] = length; + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + gcov_write_block (gcov_var.offset); +} + +#else /* IN_LIBGCOV */ + +/* Write a tag TAG and length LENGTH. */ + +GCOV_LINKAGE void +gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = length; +} + +/* Write a summary structure to the gcov file. Return nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) +{ + unsigned ix; + const struct gcov_ctr_summary *csum; + + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); + gcov_write_unsigned (summary->checksum); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + gcov_write_unsigned (csum->num); + gcov_write_unsigned (csum->runs); + gcov_write_counter (csum->sum_all); + gcov_write_counter (csum->run_max); + gcov_write_counter (csum->sum_max); + } +} +#endif /* IN_LIBGCOV */ + +#endif /*!IN_GCOV */ + +/* Return a pointer to read BYTES bytes from the gcov file. Returns + NULL on failure (read past EOF). */ + +static const gcov_unsigned_t * +gcov_read_words (unsigned words) +{ + const gcov_unsigned_t *result; + unsigned excess = gcov_var.length - gcov_var.offset; + + gcc_assert (gcov_var.mode > 0); + if (excess < words) + { + gcov_var.start += gcov_var.offset; +#if IN_LIBGCOV + if (excess) + { + gcc_assert (excess == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); + } +#else + memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); +#endif + gcov_var.offset = 0; + gcov_var.length = excess; +#if IN_LIBGCOV + gcc_assert (!gcov_var.length || gcov_var.length == 1); + excess = GCOV_BLOCK_SIZE; +#else + if (gcov_var.length + words > gcov_var.alloc) + gcov_allocate (gcov_var.length + words); + excess = gcov_var.alloc - gcov_var.length; +#endif + excess = fread (gcov_var.buffer + gcov_var.length, + 1, excess << 2, gcov_var.file) >> 2; + gcov_var.length += excess; + if (gcov_var.length < words) + { + gcov_var.overread += words - gcov_var.length; + gcov_var.length = 0; + return 0; + } + } + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + return result; +} + +/* Read unsigned value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_unsigned (void) +{ + gcov_unsigned_t value; + const gcov_unsigned_t *buffer = gcov_read_words (1); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + return value; +} + +/* Read counter value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_type +gcov_read_counter (void) +{ + gcov_type value; + const gcov_unsigned_t *buffer = gcov_read_words (2); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + if (sizeof (value) > sizeof (gcov_unsigned_t)) + value |= ((gcov_type) from_file (buffer[1])) << 32; + else if (buffer[1]) + gcov_var.error = -1; + + return value; +} + +/* Read string from coverage file. Returns a pointer to a static + buffer, or NULL on empty string. You must copy the string before + calling another gcov function. */ + +#if !IN_LIBGCOV +GCOV_LINKAGE const char * +gcov_read_string (void) +{ + unsigned length = gcov_read_unsigned (); + + if (!length) + return 0; + + return (const char *) gcov_read_words (length); +} +#endif + +GCOV_LINKAGE void +gcov_read_summary (struct gcov_summary *summary) +{ + unsigned ix; + struct gcov_ctr_summary *csum; + + summary->checksum = gcov_read_unsigned (); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + csum->num = gcov_read_unsigned (); + csum->runs = gcov_read_unsigned (); + csum->sum_all = gcov_read_counter (); + csum->run_max = gcov_read_counter (); + csum->sum_max = gcov_read_counter (); + } +} + +#if !IN_LIBGCOV +/* Reset to a known position. BASE should have been obtained from + gcov_position, LENGTH should be a record length. */ + +GCOV_LINKAGE void +gcov_sync (gcov_position_t base, gcov_unsigned_t length) +{ + gcc_assert (gcov_var.mode > 0); + base += length; + if (base - gcov_var.start <= gcov_var.length) + gcov_var.offset = base - gcov_var.start; + else + { + gcov_var.offset = gcov_var.length = 0; + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; + } +} +#endif + +#if IN_LIBGCOV +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + gcc_assert (gcov_var.mode < 0); + if (gcov_var.offset) + gcov_write_block (gcov_var.offset); + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; +} +#endif + +#if IN_GCOV > 0 +/* Return the modification time of the current gcov file. */ + +GCOV_LINKAGE time_t +gcov_time (void) +{ + struct stat status; + + if (fstat (fileno (gcov_var.file), &status)) + return 0; + else + return status.st_mtime; +} +#endif /* IN_GCOV */ diff --git a/src/lib/gcov-io.h b/src/lib/gcov-io.h new file mode 100644 index 0000000..4502bd6 --- /dev/null +++ b/src/lib/gcov-io.h @@ -0,0 +1,639 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, + 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + + +/* Coverage information is held in two files. A notes file, which is + generated by the compiler, and a data file, which is generated by + the program under test. Both files use a similar structure. We do + not attempt to make these files backwards compatible with previous + versions, as you only need coverage information when developing a + program. We do hold version information, so that mismatches can be + detected, and we use a format that allows tools to skip information + they do not understand or are not interested in. + + Numbers are recorded in the 32 bit unsigned binary form of the + endianness of the machine generating the file. 64 bit numbers are + stored as two 32 bit numbers, the low part first. Strings are + padded with 1 to 4 NUL bytes, to bring the length up to a multiple + of 4. The number of 4 bytes is stored, followed by the padded + string. Zero length and NULL strings are simply stored as a length + of zero (they have no trailing NUL or padding). + + int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3 + int64: int32:low int32:high + string: int32:0 | int32:length char* char:0 padding + padding: | char:0 | char:0 char:0 | char:0 char:0 char:0 + item: int32 | int64 | string + + The basic format of the files is + + file : int32:magic int32:version int32:stamp record* + + The magic ident is different for the notes and the data files. The + magic ident is used to determine the endianness of the file, when + reading. The version is the same for both files and is derived + from gcc's version number. The stamp value is used to synchronize + note and data files and to synchronize merging within a data + file. It need not be an absolute time stamp, merely a ticker that + increments fast enough and cycles slow enough to distinguish + different compile/run/compile cycles. + + Although the ident and version are formally 32 bit numbers, they + are derived from 4 character ASCII strings. The version number + consists of the single character major version number, a two + character minor version number (leading zero for versions less than + 10), and a single character indicating the status of the release. + That will be 'e' experimental, 'p' prerelease and 'r' for release. + Because, by good fortune, these are in alphabetical order, string + collating can be used to compare version strings. Be aware that + the 'e' designation will (naturally) be unstable and might be + incompatible with itself. For gcc 3.4 experimental, it would be + '304e' (0x33303465). When the major version reaches 10, the + letters A-Z will be used. Assuming minor increments releases every + 6 months, we have to make a major increment every 50 years. + Assuming major increments releases every 5 years, we're ok for the + next 155 years -- good enough for me. + + A record has a tag, length and variable amount of data. + + record: header data + header: int32:tag int32:length + data: item* + + Records are not nested, but there is a record hierarchy. Tag + numbers reflect this hierarchy. Tags are unique across note and + data files. Some record types have a varying amount of data. The + LENGTH is the number of 4bytes that follow and is usually used to + determine how much data. The tag value is split into 4 8-bit + fields, one for each of four possible levels. The most significant + is allocated first. Unused levels are zero. Active levels are + odd-valued, so that the LSB of the level is one. A sub-level + incorporates the values of its superlevels. This formatting allows + you to determine the tag hierarchy, without understanding the tags + themselves, and is similar to the standard section numbering used + in technical documents. Level values [1..3f] are used for common + tags, values [41..9f] for the notes file and [a1..ff] for the data + file. + + The basic block graph file contains the following records + note: unit function-graph* + unit: header int32:checksum string:source + function-graph: announce_function basic_blocks {arcs | lines}* + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + string:name string:source int32:lineno + basic_block: header int32:flags* + arcs: header int32:block_no arc* + arc: int32:dest_block int32:flags + lines: header int32:block_no line* + int32:0 string:NULL + line: int32:line_no | int32:0 string:filename + + The BASIC_BLOCK record holds per-bb flags. The number of blocks + can be inferred from its data length. There is one ARCS record per + basic block. The number of arcs from a bb is implicit from the + data length. It enumerates the destination bb and per-arc flags. + There is one LINES record per basic block, it enumerates the source + lines which belong to that basic block. Source file names are + introduced by a line number of 0, following lines are from the new + source file. The initial source file for the function is NULL, but + the current source file should be remembered from one LINES record + to the next. The end of a block is indicated by an empty filename + - this does not reset the current source file. Note there is no + ordering of the ARCS and LINES records: they may be in any order, + interleaved in any manner. The current filename follows the order + the LINES records are stored in the file, *not* the ordering of the + blocks they are for. + + The data file contains the following records. + data: {unit summary:object summary:program* function-data*}* + unit: header int32:checksum + function-data: announce_function present counts + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + present: header int32:present + counts: header int64:count* + summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE + count-summary: int32:num int32:runs int64:sum + int64:max int64:sum_max + + The ANNOUNCE_FUNCTION record is the same as that in the note file, + but without the source location. The COUNTS gives the + counter values for instrumented features. The about the whole + program. The checksum is used for whole program summaries, and + disambiguates different programs which include the same + instrumented object file. There may be several program summaries, + each with a unique checksum. The object summary's checksum is + zero. Note that the data file might contain information from + several runs concatenated, or the data might be merged. + + This file is included by both the compiler, gcov tools and the + runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to + distinguish which case is which. If IN_LIBGCOV is nonzero, + libgcov is being built. If IN_GCOV is nonzero, the gcov tools are + being built. Otherwise the compiler is being built. IN_GCOV may be + positive or negative. If positive, we are compiling a tool that + requires additional functions (see the code for knowledge of what + those functions are). */ + +#ifndef GCC_GCOV_IO_H +#define GCC_GCOV_IO_H + +#ifdef __COREBOOT__ +#define GCOV_LINKAGE /* nothing */ +/* We need the definitions for + BITS_PER_UNIT and + LONG_LONG_TYPE_SIZE + They are defined in gcc/defaults.h and gcc/config/ + (like, gcc/config/i386/i386.h). And it can be overridden by setting + in build scripts. Here I hardcoded the value for x86. */ +#define BITS_PER_UNIT 8 +#define LONG_LONG_TYPE_SIZE 64 + +/* There are many gcc_assertions. Set the vaule to 1 if we want a warning + message if the assertion fails. */ +#ifndef ENABLE_ASSERT_CHECKING +#define ENABLE_ASSERT_CHECKING 1 +#endif +#endif /* __COREBOOT__ */ + +#if IN_LIBGCOV +/* About the target */ + +#if BITS_PER_UNIT == 8 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef unsigned gcov_position_t __attribute__ ((mode (SI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (DI))); +#else +typedef signed gcov_type __attribute__ ((mode (SI))); +#endif +#else +#if BITS_PER_UNIT == 16 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); +typedef unsigned gcov_position_t __attribute__ ((mode (HI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (SI))); +#else +typedef signed gcov_type __attribute__ ((mode (HI))); +#endif +#else +typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); +typedef unsigned gcov_position_t __attribute__ ((mode (QI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (HI))); +#else +typedef signed gcov_type __attribute__ ((mode (QI))); +#endif +#endif +#endif + + +#if defined (TARGET_POSIX_IO) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#else /* !IN_LIBGCOV */ +/* About the host */ + +typedef unsigned gcov_unsigned_t; +typedef unsigned gcov_position_t; +/* gcov_type is typedef'd elsewhere for the compiler */ +#if IN_GCOV +#define GCOV_LINKAGE static +typedef HOST_WIDEST_INT gcov_type; +#if IN_GCOV > 0 +#include +#endif +#else /*!IN_GCOV */ +#define GCOV_TYPE_SIZE (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32) +#endif + +#if defined (HOST_HAS_F_SETLKW) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#endif /* !IN_LIBGCOV */ + +/* In gcov we want function linkage to be static. In the compiler we want + it extern, so that they can be accessed from elsewhere. In libgcov we + need these functions to be extern, so prefix them with __gcov. In + libgcov they must also be hidden so that the instance in the executable + is not also used in a DSO. */ +#if IN_LIBGCOV + +#ifndef __COREBOOT__ +#include "tconfig.h" +#endif /* __COREBOOT__ */ + +#define gcov_var __gcov_var +#define gcov_open __gcov_open +#define gcov_close __gcov_close +#define gcov_write_tag_length __gcov_write_tag_length +#define gcov_position __gcov_position +#define gcov_seek __gcov_seek +#define gcov_rewrite __gcov_rewrite +#define gcov_is_error __gcov_is_error +#define gcov_write_unsigned __gcov_write_unsigned +#define gcov_write_counter __gcov_write_counter +#define gcov_write_summary __gcov_write_summary +#define gcov_read_unsigned __gcov_read_unsigned +#define gcov_read_counter __gcov_read_counter +#define gcov_read_summary __gcov_read_summary + +/* Poison these, so they don't accidentally slip in. */ +#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length +#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#else + +#define ATTRIBUTE_HIDDEN + +#endif + +#ifndef GCOV_LINKAGE +#define GCOV_LINKAGE extern +#endif + +/* File suffixes. */ +#define GCOV_DATA_SUFFIX ".gcda" +#define GCOV_NOTE_SUFFIX ".gcno" + +/* File magic. Must not be palindromes. */ +#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ +#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */ + +/* gcov-iov.h is automatically generated by the makefile from + version.c, it looks like + #define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef) +*/ +#include "gcov-iov.h" + +/* Convert a magic or version number to a 4 character string. */ +#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ + ((ARRAY)[0] = (char)((VALUE) >> 24), \ + (ARRAY)[1] = (char)((VALUE) >> 16), \ + (ARRAY)[2] = (char)((VALUE) >> 8), \ + (ARRAY)[3] = (char)((VALUE) >> 0)) + +/* The record tags. Values [1..3f] are for tags which may be in either + file. Values [41..9f] for those in the note file and [a1..ff] for + the data file. The tag value zero is used as an explicit end of + file marker -- it is not required to be present. */ + +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) +#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) +#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) +#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) +#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_SUMMARY_LENGTH \ + (1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2)) + +/* Counters that are collected. */ +#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ +#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be + summaried. */ +#define GCOV_FIRST_VALUE_COUNTER 1 /* The first of counters used for value + profiling. They must form a consecutive + interval and their order must match + the order of HIST_TYPEs in + value-prof.h. */ +#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */ +#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm + of a value. */ +#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */ +#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between + consecutive values of expression. */ + +#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */ +#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the + counter. */ +#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to + counter. */ +#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value + profiling. */ +#define GCOV_COUNTERS 8 + +/* Number of counters used for value profiling. */ +#define GCOV_N_VALUE_COUNTERS \ + (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) + + /* A list of human readable names of the counters */ +#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \ + "delta", "indirect_call", "average", "ior"} + + /* Names of merge functions for counters. */ +#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_single", \ + "__gcov_merge_delta", \ + "__gcov_merge_single", \ + "__gcov_merge_add", \ + "__gcov_merge_ior"} + +/* Convert a counter index to a tag. */ +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) +/* Convert a tag to a counter. */ +#define GCOV_COUNTER_FOR_TAG(TAG) \ + ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)) +/* Check whether a tag is a counter tag. */ +#define GCOV_TAG_IS_COUNTER(TAG) \ + (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) + +/* The tag level mask has 1's in the position of the inner levels, & + the lsb of the current level, and zero on the current and outer + levels. */ +#define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG)) + +/* Return nonzero if SUB is an immediate subtag of TAG. */ +#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \ + && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG))) + +/* Return nonzero if SUB is at a sublevel to TAG. */ +#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB)) + +/* Basic block flags. */ +#define GCOV_BLOCK_UNEXPECTED (1 << 1) + +/* Arc flags. */ +#define GCOV_ARC_ON_TREE (1 << 0) +#define GCOV_ARC_FAKE (1 << 1) +#define GCOV_ARC_FALLTHROUGH (1 << 2) + +/* Structured records. */ + +/* Cumulative counter data. */ +struct gcov_ctr_summary +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_unsigned_t runs; /* number of program runs */ + gcov_type sum_all; /* sum of all counters accumulated. */ + gcov_type run_max; /* maximum value on a single run. */ + gcov_type sum_max; /* sum of individual run max values. */ +}; + +/* Object & program summary record. */ +struct gcov_summary +{ + gcov_unsigned_t checksum; /* checksum of program */ + struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; +}; + +/* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ + +#if IN_LIBGCOV +/* Information about counters for a single function. */ +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ +}; + +/* Information about a single function. This uses the trailing array + idiom. The number of counters is determined from the merge pointer + array in gcov_info. The key is used to detect which of a set of + comdat functions was selected -- it points to the gcov_info object + of the object file containing the selected comdat function. */ + +struct gcov_fn_info +{ + const struct gcov_info *key; /* comdat key */ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ + gcov_unsigned_t cfg_checksum; /* function cfg checksum */ + struct gcov_ctr_info ctrs[0]; /* instrumented counters */ +}; + +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; /* output file name */ + + gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for + unused) */ + + unsigned n_functions; /* number of functions */ + const struct gcov_fn_info *const *functions; /* pointer to pointers + to function information */ +}; + +/* Register a new object file module. */ +extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + +#ifndef __COREBOOT__ +/* Called before fork, to avoid double counting. */ +extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; +#endif + +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common value. */ +extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common difference between + consecutive values. */ +extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function that just ors the counters together. */ +extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The profiler functions. */ +extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); +extern void __gcov_pow2_profiler (gcov_type *, gcov_type); +extern void __gcov_one_value_profiler (gcov_type *, gcov_type); +extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *); +extern void __gcov_average_profiler (gcov_type *, gcov_type); +extern void __gcov_ior_profiler (gcov_type *, gcov_type); + +#ifndef inhibit_libc +/* The wrappers around some library functions.. */ +extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; +extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execve (const char *, char *const [], char *const []) + ATTRIBUTE_HIDDEN; +#endif + +#endif /* IN_LIBGCOV */ + +#if IN_LIBGCOV >= 0 + +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var ATTRIBUTE_HIDDEN; + +/* Functions for reading and writing gcov files. In libgcov you can + open the file for reading then writing. Elsewhere you can open the + file either for reading or for writing. When reading a file you may + use the gcov_read_* functions, gcov_sync, gcov_position, & + gcov_error. When writing a file you may use the gcov_write + functions, gcov_seek & gcov_error. When a file is to be rewritten + you use the functions for reading, then gcov_rewrite then the + functions for writing. Your file may become corrupted if you break + these invariants. */ +#if IN_LIBGCOV +GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; +#else +GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); +GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); +#endif +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; + +/* Available everywhere. */ +static gcov_position_t gcov_position (void); +static int gcov_is_error (void); + +GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; + +#if IN_LIBGCOV +/* Available only in libgcov */ +GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, + const struct gcov_summary *) + ATTRIBUTE_HIDDEN; +static void gcov_rewrite (void); +GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; +#else +/* Available outside libgcov */ +GCOV_LINKAGE const char *gcov_read_string (void); +GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, + gcov_unsigned_t /*length */); +#endif + +#if !IN_GCOV +/* Available outside gcov */ +GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +#endif + +#if !IN_GCOV && !IN_LIBGCOV +/* Available only in compiler */ +GCOV_LINKAGE void gcov_write_string (const char *); +GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); +GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); +#endif + +#if IN_GCOV > 0 +/* Available in gcov */ +GCOV_LINKAGE time_t gcov_time (void); +#endif + +/* Save the current position in the gcov file. */ + +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ + +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ + +static inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + +#endif /* IN_LIBGCOV >= 0 */ + +#endif /* GCC_GCOV_IO_H */ diff --git a/src/lib/gcov-iov.h b/src/lib/gcov-iov.h new file mode 100644 index 0000000..09951fb --- /dev/null +++ b/src/lib/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `4.7.2 (4 7) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3430372a) /* 407* */ diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 206e82b..eed243a 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -42,6 +42,7 @@ it with the version available from LANL. #if CONFIG_WRITE_HIGH_TABLES #include #endif +#include #include /** @@ -62,6 +63,10 @@ void hardwaremain(int boot_complete) timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); +#if CONFIG_COVERAGE + coverage_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); diff --git a/src/lib/libgcov.c b/src/lib/libgcov.c new file mode 100644 index 0000000..a32ce55 --- /dev/null +++ b/src/lib/libgcov.c @@ -0,0 +1,1158 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define __COREBOOT__ +#ifdef __COREBOOT__ +#include +#include +#include +#include +typedef s32 pid_t; +#define gcc_assert(x) ASSERT(x) +#define fprintf(file, x...) printk(BIOS_ERR, x) +#define alloca(size) __builtin_alloca (size) +#include "gcov-glue.c" + +/* Define MACROs to be used by coreboot compilation. */ +# define L_gcov +# define L_gcov_interval_profiler +# define L_gcov_pow2_profiler +# define L_gcov_one_value_profiler +# define L_gcov_indirect_call_profiler +# define L_gcov_average_profiler +# define L_gcov_ior_profiler + +# define HAVE_CC_TLS 0 +# define __GCOV_KERNEL__ + +# define IN_LIBGCOV 1 +# define IN_GCOV 0 +#else /* __COREBOOT__ */ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#endif /* __COREBOOT__ */ + +#ifndef __COREBOOT__ +#if defined(inhibit_libc) +#define IN_LIBGCOV (-1) +#else +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include +#define IN_LIBGCOV 1 +#if defined(L_gcov) +#define GCOV_LINKAGE /* nothing */ +#endif +#endif +#endif /* __COREBOOT__ */ +#include "gcov-io.h" + +#if defined(inhibit_libc) +/* If libc and its header files are not available, provide dummy functions. */ + +#ifdef L_gcov +void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} +void __gcov_flush (void) {} +#endif + +#ifdef L_gcov_merge_add +void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_single +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_delta +void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#else + +#ifndef __COREBOOT__ +#include +#if GCOV_LOCKED +#include +#include +#include +#endif +#else +void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif /* __COREBOOT__ */ + +#ifdef L_gcov +#include "gcov-io.c" + +struct gcov_fn_buffer +{ + struct gcov_fn_buffer *next; + unsigned fn_ix; + struct gcov_fn_info info; + /* note gcov_fn_info ends in a trailing array. */ +}; + +/* Chain of per-object gcov structures. */ +static struct gcov_info *gcov_list; + +/* Size of the longest file name. */ +static size_t gcov_max_filename = 0; + +/* Make sure path component of the given FILENAME exists, create + missing directories. FILENAME must be writable. + Returns zero on success, or -1 if an error occurred. */ + +static int +create_file_directory (char *filename) +{ +#ifdef __COREBOOT__ + (void) filename; + return 0; +#else +#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +#else + char *s; + + s = filename; + + if (HAS_DRIVE_SPEC(s)) + s += 2; + if (IS_DIR_SEPARATOR(*s)) + ++s; + for (; *s != '\0'; s++) + if (IS_DIR_SEPARATOR(*s)) + { + char sep = *s; + *s = '\0'; + + /* Try to make directory if it doesn't already exist. */ + if (access (filename, F_OK) == -1 +#ifdef TARGET_POSIX_IO + && mkdir (filename, 0755) == -1 +#else + && mkdir (filename) == -1 +#endif + /* The directory might have been made by another process. */ + && errno != EEXIST) + { + fprintf (stderr, "profiling:%s:Cannot create directory\n", + filename); + *s = sep; + return -1; + }; + + *s = sep; + }; + return 0; +#endif +#endif +} + +static struct gcov_fn_buffer * +free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, + unsigned limit) +{ + struct gcov_fn_buffer *next; + unsigned ix, n_ctr = 0; + + if (!buffer) + return 0; + next = buffer->next; + + for (ix = 0; ix != limit; ix++) + if (gi_ptr->merge[ix]) + free (buffer->info.ctrs[n_ctr++].values); + free (buffer); + return next; +} + +static struct gcov_fn_buffer ** +buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, + struct gcov_fn_buffer **end_ptr, unsigned fn_ix) +{ + unsigned n_ctrs = 0, ix = 0; + struct gcov_fn_buffer *fn_buffer; + unsigned len; + + for (ix = GCOV_COUNTERS; ix--;) + if (gi_ptr->merge[ix]) + n_ctrs++; + + len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; + fn_buffer = (struct gcov_fn_buffer *)malloc (len); + + if (!fn_buffer) + goto fail; + + fn_buffer->next = 0; + fn_buffer->fn_ix = fn_ix; + fn_buffer->info.ident = gcov_read_unsigned (); + fn_buffer->info.lineno_checksum = gcov_read_unsigned (); + fn_buffer->info.cfg_checksum = gcov_read_unsigned (); + + for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) + { + gcov_unsigned_t length; + gcov_type *values; + + if (!gi_ptr->merge[ix]) + continue; + + if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) + { + len = 0; + goto fail; + } + + length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); + len = length * sizeof (gcov_type); + values = (gcov_type *)malloc (len); + if (!values) + goto fail; + + fn_buffer->info.ctrs[n_ctrs].num = length; + fn_buffer->info.ctrs[n_ctrs].values = values; + + while (length--) + *values++ = gcov_read_counter (); + n_ctrs++; + } + + *end_ptr = fn_buffer; + return &fn_buffer->next; + +fail: + fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix, + len ? "cannot allocate" : "counter mismatch", len ? len : ix); + + return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); +} + +/* Add an unsigned value to the current crc */ + +static gcov_unsigned_t +crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) +{ + unsigned ix; + + for (ix = 32; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; + crc32 <<= 1; + crc32 ^= feedback; + } + + return crc32; +} + +/* Check if VERSION of the info block PTR matches libgcov one. + Return 1 on success, or zero in case of versions mismatch. + If FILENAME is not NULL, its value used for reporting purposes + instead of value from the info block. */ + +static int +gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, + const char *filename) +{ + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fprintf (stderr, + "profiling:%s:Version mismatch - expected %.4s got %.4s\n", + filename? filename : ptr->filename, e, v); + return 0; + } + return 1; +} + +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. We use this + program's checksum to make sure we only accumulate whole program + statistics to the correct summary. An object file might be embedded + in two separate programs, and we must keep the two program + summaries separate. */ + +static void +gcov_exit (void) +{ + struct gcov_info *gi_ptr; + const struct gcov_fn_info *gfi_ptr; + struct gcov_summary this_prg; /* summary for program. */ + struct gcov_summary all_prg; /* summary for all instances of program. */ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; + int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; + size_t prefix_length; + char *gi_filename, *gi_filename_up; + gcov_unsigned_t crc32 = 0; + + memset (&all_prg, 0, sizeof (all_prg)); + /* Find the totals for this execution. */ + memset (&this_prg, 0, sizeof (this_prg)); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); + crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); + + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (gfi_ptr && gfi_ptr->key != gi_ptr) + gfi_ptr = 0; + + crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); + crc32 = crc32_unsigned (crc32, + gfi_ptr ? gfi_ptr->lineno_checksum : 0); + if (!gfi_ptr) + continue; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + cs_ptr = &this_prg.ctrs[t_ix]; + cs_ptr->num += ci_ptr->num; + crc32 = crc32_unsigned (crc32, ci_ptr->num); + + for (c_num = 0; c_num < ci_ptr->num; c_num++) + { + cs_ptr->sum_all += ci_ptr->values[c_num]; + if (cs_ptr->run_max < ci_ptr->values[c_num]) + cs_ptr->run_max = ci_ptr->values[c_num]; + } + ci_ptr++; + } + } + } + +#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); + if (tmp) + { + gcov_prefix_strip = atoi (tmp); + /* Do not consider negative values. */ + if (gcov_prefix_strip < 0) + gcov_prefix_strip = 0; + } + } + + /* Get file name relocation prefix. Non-absolute values are ignored. */ + gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix) + { + prefix_length = strlen(gcov_prefix); + + /* Remove an unnecessary trailing '/' */ + if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; + } + else +#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume + relative. */ + if (gcov_prefix_strip != 0 && prefix_length == 0) + { + gcov_prefix = "."; + prefix_length = 1; + } + /* Allocate and initialize the filename scratch space plus one. */ + gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); + if (prefix_length) + memcpy (gi_filename, gcov_prefix, prefix_length); + gi_filename_up = gi_filename + prefix_length; + + /* Now merge each file. */ + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned n_counts; + struct gcov_summary prg; /* summary for this object over all + program. */ + struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all; + int error = 0; + gcov_unsigned_t tag, length; + gcov_position_t summary_pos = 0; + gcov_position_t eof_pos = 0; + const char *fname, *s; + struct gcov_fn_buffer *fn_buffer = 0; + struct gcov_fn_buffer **fn_tail = &fn_buffer; + + fname = gi_ptr->filename; + + /* Avoid to add multiple drive letters into combined path. */ + if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) + fname += 2; + + /* Build relocated filename, stripping off leading + directories from the initial filename if requested. */ + if (gcov_prefix_strip > 0) + { + int level = 0; + s = fname; + if (IS_DIR_SEPARATOR(*s)) + ++s; + + /* Skip selected directory levels. */ + for (; (*s != '\0') && (level < gcov_prefix_strip); s++) + if (IS_DIR_SEPARATOR(*s)) + { + fname = s; + level++; + } + } + + /* Update complete filename with stripped original. */ + if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + { + /* If prefix is given, add directory separator. */ + strcpy (gi_filename_up, "/"); + strcpy (gi_filename_up + 1, fname); + } + else + strcpy (gi_filename_up, fname); + + if (!gcov_open (gi_filename)) + { + /* Open failed likely due to missed directory. + Create directory and retry to open file. */ + if (create_file_directory (gi_filename)) + { + fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + continue; + } + if (!gcov_open (gi_filename)) + { + fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + continue; + } + } + + tag = gcov_read_unsigned (); + if (tag) + { + /* Merge data from file. */ + if (tag != GCOV_DATA_MAGIC) + { + fprintf (stderr, "profiling:%s:Not a gcov data file\n", + gi_filename); + goto read_fatal; + } + length = gcov_read_unsigned (); + if (!gcov_version (gi_ptr, length, gi_filename)) + goto read_fatal; + + length = gcov_read_unsigned (); + if (length != gi_ptr->stamp) + /* Read from a different compilation. Overwrite the file. */ + goto rewrite; + + /* Look for program summary. */ + for (f_ix = 0;;) + { + struct gcov_summary tmp; + + eof_pos = gcov_position (); + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_PROGRAM_SUMMARY) + break; + + f_ix--; + length = gcov_read_unsigned (); + if (length != GCOV_TAG_SUMMARY_LENGTH) + goto read_mismatch; + gcov_read_summary (&tmp); + if ((error = gcov_is_error ())) + goto read_error; + if (summary_pos || tmp.checksum != crc32) + goto next_summary; + + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num) + goto next_summary; + prg = tmp; + summary_pos = eof_pos; + + next_summary:; + } + + /* Merge execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; + f_ix++, tag = gcov_read_unsigned ()) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (tag != GCOV_TAG_FUNCTION) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (!length) + /* This function did not appear in the other program. + We have nothing to merge. */ + continue; + + if (length != GCOV_TAG_FUNCTION_LENGTH) + goto read_mismatch; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + { + /* This function appears in the other program. We + need to buffer the information in order to write + it back out -- we'll be inserting data before + this point, so cannot simply keep the data in the + file. */ + fn_tail = buffer_fn_data (gi_filename, + gi_ptr, fn_tail, f_ix); + if (!fn_tail) + goto read_mismatch; + continue; + } + + length = gcov_read_unsigned (); + if (length != gfi_ptr->ident) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->lineno_checksum) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->cfg_checksum) + goto read_mismatch; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + gcov_merge_fn merge = gi_ptr->merge[t_ix]; + + if (!merge) + continue; + + tag = gcov_read_unsigned (); + length = gcov_read_unsigned (); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) + goto read_mismatch; + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } + if ((error = gcov_is_error ())) + goto read_error; + } + + if (tag) + { + read_mismatch:; + fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n", + gi_filename, f_ix >= 0 ? "function" : "summary", + f_ix < 0 ? -1 - f_ix : f_ix); + goto read_fatal; + } + } + goto rewrite; + + read_error:; + fprintf (stderr, "profiling:%s:%s merging\n", gi_filename, + error < 0 ? "Overflow": "Error"); + + goto read_fatal; + + rewrite:; + gcov_rewrite (); + if (!summary_pos) + { + memset (&prg, 0, sizeof (prg)); + summary_pos = eof_pos; + } + + /* Merge the summaries. */ + for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) + { + cs_prg = &prg.ctrs[t_ix]; + cs_tprg = &this_prg.ctrs[t_ix]; + cs_all = &all_prg.ctrs[t_ix]; + + if (gi_ptr->merge[t_ix]) + { + if (!cs_prg->runs++) + cs_prg->num = cs_tprg->num; + cs_prg->sum_all += cs_tprg->sum_all; + if (cs_prg->run_max < cs_tprg->run_max) + cs_prg->run_max = cs_tprg->run_max; + cs_prg->sum_max += cs_tprg->run_max; + } + else if (cs_prg->runs) + goto read_mismatch; + + if (!cs_all->runs && cs_prg->runs) + memcpy (cs_all, cs_prg, sizeof (*cs_all)); + else if (!all_prg.checksum + && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) + && memcmp (cs_all, cs_prg, sizeof (*cs_all))) + { + fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n", + gi_filename, GCOV_LOCKED + ? "" : " or concurrently updated without locking support"); + all_prg.checksum = ~0u; + } + } + + prg.checksum = crc32; + + /* Write out the data. */ + if (!eof_pos) + { + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); + } + + if (summary_pos) + gcov_seek (summary_pos); + + /* Generate whole program statistics. */ + gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg); + + if (summary_pos < eof_pos) + gcov_seek (eof_pos); + + /* Write execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + unsigned buffered = 0; + + if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix) + { + /* Buffered data from another program. */ + buffered = 1; + gfi_ptr = &fn_buffer->info; + length = GCOV_TAG_FUNCTION_LENGTH; + } + else + { + gfi_ptr = gi_ptr->functions[f_ix]; + if (gfi_ptr && gfi_ptr->key == gi_ptr) + length = GCOV_TAG_FUNCTION_LENGTH; + else + length = 0; + } + + gcov_write_tag_length (GCOV_TAG_FUNCTION, length); + if (!length) + continue; + + gcov_write_unsigned (gfi_ptr->ident); + gcov_write_unsigned (gfi_ptr->lineno_checksum); + gcov_write_unsigned (gfi_ptr->cfg_checksum); + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + n_counts = ci_ptr->num; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + gcov_type *c_ptr = ci_ptr->values; + while (n_counts--) + gcov_write_counter (*c_ptr++); + ci_ptr++; + } + if (buffered) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + } + + gcov_write_unsigned (0); + + read_fatal:; + while (fn_buffer) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + + if ((error = gcov_close ())) + fprintf (stderr, error < 0 ? + "profiling:%s:Overflow writing\n" : + "profiling:%s:Error writing\n", + gi_filename); + } +} + +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + +void +__gcov_init (struct gcov_info *info) +{ + if (!info->version || !info->n_functions) + return; + if (gcov_version (info, info->version, 0)) + { + size_t filename_length = strlen(info->filename); + + /* Refresh the longest file name information */ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + +#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); +#endif + + info->next = gcov_list; + gcov_list = info; + } + info->version = 0; +} + +/* Called before fork or exec - write out profile information gathered so + far and reset it to zero. This avoids duplication or loss of the + profile information gathered so far. */ + +void +__gcov_flush (void) +{ + const struct gcov_info *gi_ptr; + + gcov_exit (); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + +#endif /* L_gcov */ + +#ifdef L_gcov_merge_add +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_add (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters += gcov_read_counter (); +} +#endif /* L_gcov_merge_add */ + +#ifdef L_gcov_merge_ior +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_ior (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters |= gcov_read_counter (); +} +#endif + +#ifdef L_gcov_merge_single +/* The profile merging function for choosing the most common value. + * It is given an array COUNTERS of N_COUNTERS old counters and it + * reads the same number of counters from the gcov file. The counters + * are split into 3-tuples where the members of the tuple have + * meanings: + * + * -- the stored candidate on the most common value of the measured entity + * -- counter + * -- total number of evaluations of the value + */ +void +__gcov_merge_single (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 3)); + n_measures = n_counters / 3; + for (i = 0; i < n_measures; i++, counters += 3) + { + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[0] == value) + counters[1] += counter; + else if (counter > counters[1]) + { + counters[0] = value; + counters[1] = counter - counters[1]; + } + else + counters[1] -= counter; + counters[2] += all; + } +} +#endif /* L_gcov_merge_single */ + +#ifdef L_gcov_merge_delta +/* The profile merging function for choosing the most common + difference between two consecutive evaluations of the value. It is + given an array COUNTERS of N_COUNTERS old counters and it reads the + same number of counters from the gcov file. The counters are split + into 4-tuples where the members of the tuple have meanings: + + -- the last value of the measured entity + -- the stored candidate on the most common difference + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_delta (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 4)); + n_measures = n_counters / 4; + for (i = 0; i < n_measures; i++, counters += 4) + { + /* last = */ gcov_read_counter (); + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[1] == value) + counters[2] += counter; + else if (counter > counters[2]) + { + counters[1] = value; + counters[2] = counter - counters[2]; + } + else + counters[2] -= counter; + counters[3] += all; + } +} +#endif /* L_gcov_merge_delta */ + +#ifdef L_gcov_interval_profiler +/* If VALUE is in interval , then increases the + corresponding counter in COUNTERS. If the VALUE is above or below + the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased + instead. */ + +void +__gcov_interval_profiler (gcov_type *counters, gcov_type value, + int start, unsigned steps) +{ + gcov_type delta = value - start; + if (delta < 0) + counters[steps + 1]++; + else if (delta >= steps) + counters[steps]++; + else + counters[delta]++; +} +#endif + +#ifdef L_gcov_pow2_profiler +/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise + COUNTERS[0] is incremented. */ + +void +__gcov_pow2_profiler (gcov_type *counters, gcov_type value) +{ + if (value & (value - 1)) + counters[0]++; + else + counters[1]++; +} +#endif + +/* Tries to determine the most common value among its inputs. Checks if the + value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] + is incremented. If this is not the case and COUNTERS[1] is not zero, + COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and + VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this + function is called more than 50% of the time with one value, this value + will be in COUNTERS[0] in the end. + + In any case, COUNTERS[2] is incremented. */ + +static inline void +__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) +{ + if (value == counters[0]) + counters[1]++; + else if (counters[1] == 0) + { + counters[1] = 1; + counters[0] = value; + } + else + counters[1]--; + counters[2]++; +} + +#ifdef L_gcov_one_value_profiler +void +__gcov_one_value_profiler (gcov_type *counters, gcov_type value) +{ + __gcov_one_value_profiler_body (counters, value); +} +#endif + +#ifdef L_gcov_indirect_call_profiler + +/* By default, the C++ compiler will use function addresses in the + vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero + tells the compiler to use function descriptors instead. The value + of this macro says how many words wide the descriptor is (normally 2), + but it may be dependent on target flags. Since we do not have access + to the target flags here we just check to see if it is set and use + that to set VTABLE_USES_DESCRIPTORS to 0 or 1. + + It is assumed that the address of a function descriptor may be treated + as a pointer to a function. */ + +#ifdef TARGET_VTABLE_USES_DESCRIPTORS +#define VTABLE_USES_DESCRIPTORS 1 +#else +#define VTABLE_USES_DESCRIPTORS 0 +#endif + +/* Tries to determine the most common value among its inputs. */ +void +__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, + void* cur_func, void* callee_func) +{ + /* If the C++ virtual tables contain function descriptors then one + function may have multiple descriptors and we need to dereference + the descriptors to see if they point to the same function. */ + if (cur_func == callee_func + || (VTABLE_USES_DESCRIPTORS && callee_func + && *(void **) cur_func == *(void **) callee_func)) + __gcov_one_value_profiler_body (counter, value); +} +#endif + + +#ifdef L_gcov_average_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_average_profiler (gcov_type *counters, gcov_type value) +{ + counters[0] += value; + counters[1] ++; +} +#endif + +#ifdef L_gcov_ior_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_ior_profiler (gcov_type *counters, gcov_type value) +{ + *counters |= value; +} +#endif + +#ifdef L_gcov_fork +/* A wrapper for the fork function. Flushes the accumulated profiling data, so + that they are not counted twice. */ + +pid_t +__gcov_fork (void) +{ + __gcov_flush (); + return fork (); +} +#endif + +#ifdef L_gcov_execl +/* A wrapper for the execl function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execl (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execv (path, args); +} +#endif + +#ifdef L_gcov_execlp +/* A wrapper for the execlp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execlp (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execvp (path, args); +} +#endif + +#ifdef L_gcov_execle +/* A wrapper for the execle function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execle (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + char **envp; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + envp = va_arg (aq, char **); + va_end (aq); + + return execve (path, args, envp); +} +#endif + +#ifdef L_gcov_execv +/* A wrapper for the execv function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execv (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execv (path, argv); +} +#endif + +#ifdef L_gcov_execvp +/* A wrapper for the execvp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execvp (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execvp (path, argv); +} +#endif + +#ifdef L_gcov_execve +/* A wrapper for the execve function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execve (const char *path, char *const argv[], char *const envp[]) +{ + __gcov_flush (); + return execve (path, argv, envp); +} +#endif +#endif /* inhibit_libc */ diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 2556a14..c5fb62a 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -32,6 +32,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR @@ -518,6 +519,9 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) #if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); #endif +#if CONFIG_COVERAGE + coverage_exit(); +#endif /* Before we go off to run the payload, see if * we stayed within our bounds. diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index a777a8f..bc6bd6b 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define MAP_BYTES (1024*1024) @@ -82,7 +84,7 @@ static void *map_memory(u64 physical) /* Mapped memory must be aligned to page size */ p = physical & ~(page - 1); - debug("Mapping 1MB of physical memory at %zx.\n", p); + debug("Mapping 1MB of physical memory at 0x%zx.\n", p); v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); @@ -103,8 +105,13 @@ static void *map_memory(u64 physical) static void unmap_memory(void) { + if (mapped_virtual == NULL) { + fprintf(stderr, "Error unmapping memory\n"); + return; + } debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); munmap(mapped_virtual, MAP_BYTES); + mapped_virtual = NULL; } /* @@ -347,7 +354,7 @@ struct cbmem_entry { uint64_t size; }; -void dump_cbmem_toc(void) +static void dump_cbmem_toc(void) { int i; uint64_t start; @@ -374,7 +381,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_GDT: printf("GDT "); break; case CBMEM_ID_ACPI: printf("ACPI "); break; case CBMEM_ID_ACPI_GNVS: printf("ACPI GNVS "); break; - case CBMEM_ID_CBTABLE: printf("COREBOOTE "); break; + case CBMEM_ID_CBTABLE: printf("COREBOOT "); break; case CBMEM_ID_PIRQ: printf("IRQ TABLE "); break; case CBMEM_ID_MPTABLE: printf("SMP TABLE "); break; case CBMEM_ID_RESUME: printf("ACPI RESUME "); break; @@ -384,6 +391,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_MRCDATA: printf("MRC DATA "); break; case CBMEM_ID_CONSOLE: printf("CONSOLE "); break; case CBMEM_ID_ELOG: printf("ELOG "); break; + case CBMEM_ID_COVERAGE: printf("COVERAGE "); break; default: printf("%08x ", entries[i].id); break; } @@ -393,7 +401,111 @@ void dump_cbmem_toc(void) unmap_memory(); } -void print_version(void) +#define COVERAGE_MAGIC 0x584d4153 +struct file { + uint32_t magic; + uint32_t next; + uint32_t filename; + uint32_t data; + int offset; + int len; +}; + +static int mkpath(char *path, mode_t mode) +{ + assert (path && *path); + char *p; + for (p = strchr(path+1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) { + *p = '/'; + return -1; + } + } + *p = '/'; + } + return 0; +} + +static void dump_coverage(void) +{ + int i, found = 0; + uint64_t start; + struct cbmem_entry *entries; + void *coverage; + unsigned long phys_offset; +#define phys_to_virt(x) ((void *)(unsigned long)(x) + phys_offset) + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + for (i=0; imagic == COVERAGE_MAGIC) { + FILE *f; + char *filename; + + debug(" -> %s\n", (char *)phys_to_virt(file->filename)); + filename = strdup((char *)phys_to_virt(file->filename)); + if (mkpath(filename, 0755) == -1) { + perror("Directory for coverage data could " + "not be created"); + exit(1); + } + f = fopen(filename, "wb"); + if (!f) { + printf("Could not open %s: %s\n", + filename, strerror(errno)); + exit(1); + } + if (fwrite((void *)phys_to_virt(file->data), + file->len, 1, f) != 1) { + printf("Could not write to %s: %s\n", + filename, strerror(errno)); + exit(1); + } + fclose(f); + free(filename); + + if (file->next) + file = (struct file *)phys_to_virt(file->next); + else + file = NULL; + } + unmap_memory(); +} + +static void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); printf("Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.\n\n"); @@ -409,11 +521,12 @@ void print_version(void) "along with this program. If not, see .\n\n"); } -void print_usage(const char *name) +static void print_usage(const char *name) { - printf("usage: %s [-vh?]\n", name); + printf("usage: %s [-cCltVvh?]\n", name); printf("\n" " -c | --console: print cbmem console\n" + " -C | --coverage: dump coverage information\n" " -l | --list: print cbmem table of contents\n" " -t | --timestamps: print timestamp information\n" " -V | --verbose: verbose (debugging) output\n" @@ -430,12 +543,14 @@ int main(int argc, char** argv) int print_defaults = 1; int print_console = 0; + int print_coverage = 0; int print_list = 0; int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { {"console", 0, 0, 'c'}, + {"coverage", 0, 0, 'C'}, {"list", 0, 0, 'l'}, {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, @@ -443,13 +558,17 @@ int main(int argc, char** argv) {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cltVvh?", + while ((opt = getopt_long(argc, argv, "cCltVvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': print_console = 1; print_defaults = 0; break; + case 'C': + print_coverage = 1; + print_defaults = 0; + break; case 'l': print_list = 1; print_defaults = 0; @@ -490,6 +609,9 @@ int main(int argc, char** argv) if (print_console) dump_console(); + if (print_coverage) + dump_coverage(); + if (print_list) dump_cbmem_toc(); From gerrit at coreboot.org Wed Jan 9 02:27:05 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Wed, 9 Jan 2013 02:27:05 +0100 Subject: [coreboot] New patch to review for coreboot: 9ae4509 ARM bootblock approach (incomplete) References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2118 -gerrit commit 9ae4509487f951abe921b5647ffa1fa953bf6617 Author: Stefan Reinauer Date: Wed Jan 9 02:25:43 2013 +0100 ARM bootblock approach (incomplete) Do not attempt to commit, just making this available so it doesn't get lost Change-Id: I9cc2a8191d2db38b27b6363ba673e5a360de9684 Signed-off-by: Stefan Reinauer --- src/arch/armv7/Makefile.inc | 23 +++++------ src/arch/armv7/bootblock.inc | 82 +++++++++++++++++++++++++++++++++++++++ src/arch/armv7/bootblock.lds | 49 +++++++++++++++++++++++ src/arch/armv7/bootblock_simple.c | 12 +----- src/arch/armv7/lib/id.lds | 2 +- 5 files changed, 142 insertions(+), 26 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..7702859 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -223,19 +223,14 @@ $(obj)/coreboot.pre: $(objcbfs)/romstage_xip.elf $(obj)/coreboot.pre1 $(CBFSTOOL ################################################################################ # Build the bootblock -#bootblock_lds = $(src)/arch/armv7/ldscript_fallback_cbfs.lb -bootblock_lds = $(src)/arch/armv7/lib/id.lds -#bootblock_lds = $(src)/arch/armv7/romstage.ld +bootblock_lds = $(src)/arch/armv7/bootblock.lds +bootblock_lds += $(src)/arch/armv7/lib/id.lds bootblock_lds += $(chipset_bootblock_lds) +bootblock_inc += $(src)/arch/armv7/bootblock.inc bootblock_inc += $(src)/arch/armv7/lib/id.inc bootblock_inc += $(chipset_bootblock_inc) - -# FIXME: CONFIG_NEON or something similar for ARM? -#ifeq ($(CONFIG_SSE),y) -#bootblock_inc += $(src)/cpu/x86/sse_enable.inc -#endif -#bootblock_inc += $(objgenerated)/bootblock.inc +bootblock_inc += $(objgenerated)/bootblock.inc $(objgenerated)/bootblock.ld: $$(bootblock_lds) $(obj)/ldoptions @printf " GEN $(subst $(obj)/,,$(@))\n" @@ -253,11 +248,11 @@ $(objgenerated)/bootblock.s: $(objgenerated)/bootblock_inc.S $(obj)/config.h $(o @printf " CC $(subst $(obj)/,,$(@))\n" $(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/armv7/include -I$(obj) -include $(obj)/build.h -include $(obj)/config.h -I. -I$(src) $< -o $@ -#$(objgenerated)/bootblock.inc: $(src)/arch/armv7/init/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(objutil)/romcc/romcc $(OPTION_TABLE_H) -# @printf " ROMCC $(subst $(obj)/,,$(@))\n" -# $(CC) $(INCLUDES) -MM -MT$(objgenerated)/bootblock.inc \ -# $< > $(objgenerated)/bootblock.inc.d -# $(ROMCC) -c -S $(bootblock_romccflags) $(ROMCCFLAGS) -I. $(INCLUDES) $< -o $@ +$(objgenerated)/bootblock.inc: $(src)/arch/armv7/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(OPTION_TABLE_H) + @printf " ROMCC $(subst $(obj)/,,$(@))\n" + $(CC) $(INCLUDES) -MM -MT$(objgenerated)/bootblock.inc \ + $< > $(objgenerated)/bootblock.inc.d + $(CC) -c -S $(CFLAGS) -I. $(INCLUDES) $< -o $@ $(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.o $(objgenerated)/bootblock.ld @printf " LINK $(subst $(obj)/,,$(@))\n" diff --git a/src/arch/armv7/bootblock.inc b/src/arch/armv7/bootblock.inc new file mode 100644 index 0000000..971b5eb --- /dev/null +++ b/src/arch/armv7/bootblock.inc @@ -0,0 +1,82 @@ +/* + * Early initialization code for ARMv7 architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gr?ger + * Copyright (c) 2002 Alex Z?pke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +_bl1: + /* For now we have to live with a first stage boot loader + * on ARM, which is 8KB in size and it is prepended to the + * reset vector + */ + .skip 8192 + +.globl _start +_start: b reset + .balignl 16,0xdeadbeef + +_cbfs_master_header: + /* The CBFS master header is inserted here by cbfstool + * when coreboot.rom is being created. Hence, we leave + * some space for it. + */ + .skip 64 + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr,r0 + + /* + * From Cortex-A Series Programmer's Guide: + * Only CPU 0 performs initialization. Other CPUs go into WFI + * to do this, first work out which CPU this is + * this code typically is run before any other initialization step + */ + mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register + and r1, r1, #0x3 @ Extract CPU ID bits + cmp r1, #0 + bne wait_for_interrupt @ If this is not core0, wait + +/* Set stackpointer in internal RAM to call board_init_f */ +call_bootblock: + ldr sp, =(0x0204F800) /* Set up stack pointer */ + mov sp, r0 + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr r0,=0x00000000 + bl main + +wait_for_interrupt: + wfi + mov pc, lr @ back to my caller diff --git a/src/arch/armv7/bootblock.lds b/src/arch/armv7/bootblock.lds new file mode 100644 index 0000000..90e37a0 --- /dev/null +++ b/src/arch/armv7/bootblock.lds @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +TARGET(binary) +SECTIONS +{ + ROMLOC = 0x2023400 - 8192; + + /* This section might be better named .setup */ + .rom ROMLOC : { + _rom = .; + *(.text); + *(.text.*); + *(.rom.text); + *(.rom.data); + *(.rom.data.*); + *(.rodata.*); + _erom = .; + } = 0xff + + /DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.ARM.*) + } +} diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index f447a29..64da46c 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -23,24 +23,14 @@ #include - -#include "../../lib/uart8250.c" -#include "lib/div.c" - -struct uart8250 uart = { - 115200 -}; - void main(unsigned long bist) { - init_uart8250(CONFIG_TTYS0_BASE, &uart); - uart8250_tx_byte(CONFIG_TTYS0_BASE, '@'); - if (boot_cpu()) { bootblock_cpu_init(); bootblock_northbridge_init(); bootblock_southbridge_init(); } + const char* target1 = "fallback/romstage"; unsigned long entry; entry = findstage(target1); diff --git a/src/arch/armv7/lib/id.lds b/src/arch/armv7/lib/id.lds index 9e31ee6..22b4a02 100644 --- a/src/arch/armv7/lib/id.lds +++ b/src/arch/armv7/lib/id.lds @@ -1,5 +1,5 @@ SECTIONS { - . = (0x100000000 - CONFIG_ID_SECTION_OFFSET) - (__id_end - __id_start); + . = (0x2024000) - (__id_end - __id_start); .id (.): { *(.id) } From gerrit at coreboot.org Wed Jan 9 19:20:21 2013 From: gerrit at coreboot.org (Martin Roth (martin@se-eng.com)) Date: Wed, 9 Jan 2013 19:20:21 +0100 Subject: [coreboot] New patch to review for coreboot: c8c5522 Fix 2 infinite loops if IMC doesn't respond References: Message-ID: Martin Roth (martin at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2119 -gerrit commit c8c5522e624b266283316ee6fd979c80306b4a81 Author: Martin Roth Date: Tue Jan 8 13:36:14 2013 -0700 Fix 2 infinite loops if IMC doesn't respond ACPI code: The ACPI code is not currently being compiled in by default, but assuming that it will be at some point, I'm fixing the loop that waits for the IMC to respond after sending it a command. The loop now exits after 500ms, similar to the function in agesa. Agesa Code: a 16 bit variable will always be less than 100000. Change to be a 32 bit variable. Change-Id: I9430ef900a22d056871b744f3b1511abdfea516e Signed-off-by: Martin Roth --- src/mainboard/amd/parmer/acpi/AmdImc.asl | 4 +++- src/mainboard/amd/thatcher/acpi/AmdImc.asl | 4 +++- src/vendorcode/amd/agesa/f15tn/Proc/Fch/Imc/ImcLib.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mainboard/amd/parmer/acpi/AmdImc.asl b/src/mainboard/amd/parmer/acpi/AmdImc.asl index 937c10a..f55a12a 100644 --- a/src/mainboard/amd/parmer/acpi/AmdImc.asl +++ b/src/mainboard/amd/parmer/acpi/AmdImc.asl @@ -18,9 +18,11 @@ IndexField(IMCX, IMCA, ByteAcc, NoLock, Preserve) { Method(WACK, 0) { Store(0, Local0) - While (LNotEqual(Local0, 0xFA)) { + Store(50, Local1) + While (LAnd (LNotEqual(Local0, 0xFA), LGreater(Local1,0))) { Store(MRG0, Local0) Sleep(10) + Decrement(Local1) } } diff --git a/src/mainboard/amd/thatcher/acpi/AmdImc.asl b/src/mainboard/amd/thatcher/acpi/AmdImc.asl index 937c10a..f55a12a 100644 --- a/src/mainboard/amd/thatcher/acpi/AmdImc.asl +++ b/src/mainboard/amd/thatcher/acpi/AmdImc.asl @@ -18,9 +18,11 @@ IndexField(IMCX, IMCA, ByteAcc, NoLock, Preserve) { Method(WACK, 0) { Store(0, Local0) - While (LNotEqual(Local0, 0xFA)) { + Store(50, Local1) + While (LAnd (LNotEqual(Local0, 0xFA), LGreater(Local1,0))) { Store(MRG0, Local0) Sleep(10) + Decrement(Local1) } } diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Imc/ImcLib.c b/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Imc/ImcLib.c index 6f8903c..d8df41a 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Imc/ImcLib.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Imc/ImcLib.c @@ -126,7 +126,7 @@ WaitForEcLDN9MailboxCmdAck ( ) { UINT8 Msgdata; - UINT16 Delaytime; + UINT32 Delaytime; Msgdata = 0; From gerrit at coreboot.org Wed Jan 9 19:29:08 2013 From: gerrit at coreboot.org (Martin Roth (martin@se-eng.com)) Date: Wed, 9 Jan 2013 19:29:08 +0100 Subject: [coreboot] New patch to review for coreboot: c45b3bc Fix typo in SB800 Kconfig for IMC position References: Message-ID: Martin Roth (martin at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2120 -gerrit commit c45b3bc6741c01c88f21ff7625195c3f43f8620c Author: Martin Roth Date: Tue Jan 8 13:46:50 2013 -0700 Fix typo in SB800 Kconfig for IMC position The cimx/sb800 IMC Firmware location Kconfig option has a typo which would could set it to the wrong location. Change-Id: I38016bebd1bfe6ad6d3f1c02cb1960712fbf4ab2 Signed-off-by: Martin Roth --- src/southbridge/amd/cimx/sb800/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/southbridge/amd/cimx/sb800/Kconfig b/src/southbridge/amd/cimx/sb800/Kconfig index 54c38d8..1f3ee9a 100644 --- a/src/southbridge/amd/cimx/sb800/Kconfig +++ b/src/southbridge/amd/cimx/sb800/Kconfig @@ -191,7 +191,7 @@ config SB800_FWM_POSITION default 0xFFF20000 if SB800_FWM_AT_FFF20000 default 0xFFE20000 if SB800_FWM_AT_FFE20000 default 0xFFC20000 if SB800_FWM_AT_FFC20000 - default 0xFF820000 if SB800_FWM_AT_FFE20000 + default 0xFF820000 if SB800_FWM_AT_FF820000 endif #SB800_IMC_FWM From gerrit at coreboot.org Wed Jan 9 20:52:47 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Wed, 9 Jan 2013 20:52:47 +0100 Subject: [coreboot] Patch merged into coreboot/master: 238780c Fix typo in SB800 Kconfig for IMC position References: Message-ID: the following patch was just integrated into master: commit 238780c8da866c0f8a80a4c0004bc81d2a060a8d Author: Martin Roth Date: Tue Jan 8 13:46:50 2013 -0700 Fix typo in SB800 Kconfig for IMC position The cimx/sb800 IMC Firmware location Kconfig option has a typo which would could set it to the wrong location. Change-Id: I38016bebd1bfe6ad6d3f1c02cb1960712fbf4ab2 Signed-off-by: Martin Roth Reviewed-on: http://review.coreboot.org/2120 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi Reviewed-By: Patrick Georgi at Wed Jan 9 20:52:46 2013, giving +2 See http://review.coreboot.org/2120 for details. -gerrit From gerrit at coreboot.org Wed Jan 9 23:32:55 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 9 Jan 2013 23:32:55 +0100 Subject: [coreboot] Patch set updated for coreboot: 2a571ce ARM bootblock approach (incomplete) References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2118 -gerrit commit 2a571ceb9e58759cc06bf9fa5831ddc61180393b Author: David Hendricks Date: Tue Jan 8 21:05:06 2013 -0800 ARM bootblock approach (incomplete) Do not attempt to commit, just making this available so it doesn't get lost Note: Apply "patchdump" patch set 12 or later for this to reach the bootblock's main() function. Change-Id: I9cc2a8191d2db38b27b6363ba673e5a360de9684 Signed-off-by: Stefan Reinauer Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 26 ++++----- src/arch/armv7/bootblock.inc | 87 +++++++++++++++++++++++++++++ src/arch/armv7/bootblock.lds | 49 ++++++++++++++++ src/arch/armv7/bootblock_simple.c | 33 +++++------ src/arch/armv7/include/arch/cbfs.h | 53 ++++++++++++++++++ src/arch/armv7/include/bootblock_common.h | 71 +++-------------------- src/arch/armv7/init.S | 93 ------------------------------- src/arch/armv7/lib/id.lds | 2 +- src/cpu/samsung/exynos5250/Kconfig | 4 +- src/cpu/samsung/exynos5250/Makefile.inc | 2 +- 10 files changed, 228 insertions(+), 192 deletions(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index 8176f9a..e97e2d7 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -49,7 +49,7 @@ prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) $(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \ -B $(objcbfs)/bootblock.bin -a 64 \ - -o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) )) + -o $(CONFIG_BOOTBLOCK_OFFSET) $(prebuild-files) true mv $@.tmp $@ else @@ -149,7 +149,6 @@ CFLAGS += \ # For various headers imported from Linux CFLAGS += -D__LINUX_ARM_ARCH__=7 -crt0s = $(src)/arch/armv7/init.S ldscripts = ldscripts += $(src)/arch/armv7/romstage.ld @@ -223,19 +222,14 @@ $(obj)/coreboot.pre: $(objcbfs)/romstage_xip.elf $(obj)/coreboot.pre1 $(CBFSTOOL ################################################################################ # Build the bootblock -#bootblock_lds = $(src)/arch/armv7/ldscript_fallback_cbfs.lb -bootblock_lds = $(src)/arch/armv7/lib/id.lds -#bootblock_lds = $(src)/arch/armv7/romstage.ld +bootblock_lds = $(src)/arch/armv7/bootblock.lds +bootblock_lds += $(src)/arch/armv7/lib/id.lds bootblock_lds += $(chipset_bootblock_lds) +bootblock_inc += $(src)/arch/armv7/bootblock.inc bootblock_inc += $(src)/arch/armv7/lib/id.inc bootblock_inc += $(chipset_bootblock_inc) - -# FIXME: CONFIG_NEON or something similar for ARM? -#ifeq ($(CONFIG_SSE),y) -#bootblock_inc += $(src)/cpu/x86/sse_enable.inc -#endif -#bootblock_inc += $(objgenerated)/bootblock.inc +bootblock_inc += $(objgenerated)/bootblock.inc $(objgenerated)/bootblock.ld: $$(bootblock_lds) $(obj)/ldoptions @printf " GEN $(subst $(obj)/,,$(@))\n" @@ -253,11 +247,11 @@ $(objgenerated)/bootblock.s: $(objgenerated)/bootblock_inc.S $(obj)/config.h $(o @printf " CC $(subst $(obj)/,,$(@))\n" $(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/armv7/include -I$(obj) -include $(obj)/build.h -include $(obj)/config.h -I. -I$(src) $< -o $@ -#$(objgenerated)/bootblock.inc: $(src)/arch/armv7/init/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(objutil)/romcc/romcc $(OPTION_TABLE_H) -# @printf " ROMCC $(subst $(obj)/,,$(@))\n" -# $(CC) $(INCLUDES) -MM -MT$(objgenerated)/bootblock.inc \ -# $< > $(objgenerated)/bootblock.inc.d -# $(ROMCC) -c -S $(bootblock_romccflags) $(ROMCCFLAGS) -I. $(INCLUDES) $< -o $@ +$(objgenerated)/bootblock.inc: $(src)/arch/armv7/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(OPTION_TABLE_H) + @printf " CC $(subst $(obj)/,,$(@))\n" + $(CC) $(INCLUDES) -MM -MT$(objgenerated)/bootblock.inc \ + $< > $(objgenerated)/bootblock.inc.d + $(CC) -c -S $(CFLAGS) -I. $(INCLUDES) $< -o $@ $(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.o $(objgenerated)/bootblock.ld @printf " LINK $(subst $(obj)/,,$(@))\n" diff --git a/src/arch/armv7/bootblock.inc b/src/arch/armv7/bootblock.inc new file mode 100644 index 0000000..90850d6 --- /dev/null +++ b/src/arch/armv7/bootblock.inc @@ -0,0 +1,87 @@ +/* + * Early initialization code for ARMv7 architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gr?ger + * Copyright (c) 2002 Alex Z?pke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +_bl1: + /* For now we have to live with a first stage boot loader + * on ARM, which is 8KB in size and it is prepended to the + * reset vector + */ + .skip 8192 + +.globl _start +_start: b reset + .balignl 16,0xdeadbeef + +_cbfs_master_header: + /* The CBFS master header is inserted here by cbfstool + * when coreboot.rom is being created. Hence, we leave + * some space for it. + */ + .skip 64 + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr,r0 + + /* + * From Cortex-A Series Programmer's Guide: + * Only CPU 0 performs initialization. Other CPUs go into WFI + * to do this, first work out which CPU this is + * this code typically is run before any other initialization step + */ + mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register + and r1, r1, #0x3 @ Extract CPU ID bits + cmp r1, #0 + bne wait_for_interrupt @ If this is not core0, wait + +/* Set stackpointer in internal RAM to call board_init_f */ +call_bootblock: + ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* Set up stack pointer */ + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr r0,=0x00000000 + /* + * Use "bl" instead of "b" even though we do not intend to return. + * "bl" gets compiled to "blx" if we're transitioning from ARM to + * Thumb. However, "b" will not and GCC may attempt to create a + * wrapper which is currently broken. + */ + bl main + +wait_for_interrupt: + wfi + mov pc, lr @ back to my caller diff --git a/src/arch/armv7/bootblock.lds b/src/arch/armv7/bootblock.lds new file mode 100644 index 0000000..90e37a0 --- /dev/null +++ b/src/arch/armv7/bootblock.lds @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +TARGET(binary) +SECTIONS +{ + ROMLOC = 0x2023400 - 8192; + + /* This section might be better named .setup */ + .rom ROMLOC : { + _rom = .; + *(.text); + *(.text.*); + *(.rom.text); + *(.rom.data); + *(.rom.data.*); + *(.rodata.*); + _erom = .; + } = 0xff + + /DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.ARM.*) + } +} diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index f447a29..772a7b2 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -19,33 +19,30 @@ * MA 02110-1301 USA */ - - #include +#include - -#include "../../lib/uart8250.c" -#include "lib/div.c" - -struct uart8250 uart = { - 115200 -}; +static int boot_cpu(void) +{ + /* + * FIXME: This is a stub for now. All non-boot CPUs should be + * waiting for an interrupt. We could move the chunk of assembly + * which puts them to sleep in here... + */ + return 1; +} void main(unsigned long bist) { - init_uart8250(CONFIG_TTYS0_BASE, &uart); - uart8250_tx_byte(CONFIG_TTYS0_BASE, '@'); + const char *target1 = "fallback/romstage"; + unsigned long entry; if (boot_cpu()) { - bootblock_cpu_init(); - bootblock_northbridge_init(); - bootblock_southbridge_init(); + bootblock_mainboard_init(); } - const char* target1 = "fallback/romstage"; - unsigned long entry; + entry = findstage(target1); - if (entry) call(entry, bist); + if (entry) call(entry); hlt(); } - diff --git a/src/arch/armv7/include/arch/cbfs.h b/src/arch/armv7/include/arch/cbfs.h new file mode 100644 index 0000000..363d26c --- /dev/null +++ b/src/arch/armv7/include/arch/cbfs.h @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __INCLUDE_ARCH_CBFS__ +#define __INCLUDE_ARCH_CBFS__ + +static void *walkcbfs(const char *target) +{ + /* FIXME: stubbed out for now */ + return (void *)0; +#if 0 + void *entry; + asm volatile ( + "mov $1f, %%esp\n\t" + "jmp walkcbfs_asm\n\t" + "1:\n\t" : "=a" (entry) : "S" (target) : "ebx", "ecx", "edi", "esp"); + return entry; +#endif +} + +/* just enough to support findstage. copied because the original version doesn't easily pass through romcc */ +struct cbfs_stage_restricted { + unsigned long compression; + unsigned long entry; // this is really 64bit, but properly endianized +}; + +static inline unsigned long findstage(const char *target) +{ + return ((struct cbfs_stage_restricted *)walkcbfs(target))->entry; +} + +static inline void call(unsigned long addr) +{ + void (*doit)(void) = (void *)addr; + doit(); +} +#endif diff --git a/src/arch/armv7/include/bootblock_common.h b/src/arch/armv7/include/bootblock_common.h index f5c7129..9565593 100644 --- a/src/arch/armv7/include/bootblock_common.h +++ b/src/arch/armv7/include/bootblock_common.h @@ -1,69 +1,16 @@ -#include -#include -#include -#include - - -#define boot_cpu(x) 1 +#include #ifdef CONFIG_BOOTBLOCK_CPU_INIT #include CONFIG_BOOTBLOCK_CPU_INIT -#else -static void bootblock_cpu_init(void) { } -#endif -#ifdef CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT -#include CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT -#else -static void bootblock_northbridge_init(void) { } -#endif -#ifdef CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT -#include CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT -#else -static void bootblock_southbridge_init(void) { } #endif -static int cbfs_check_magic(struct cbfs_file *file) -{ - return !strcmp(file->magic, CBFS_FILE_MAGIC) ? 1 : 0; -} - -static unsigned long findstage(const char* target) -{ - unsigned long offset; - - void *ptr = (void *)*((unsigned long *) CBFS_HEADPTR_ADDR); - struct cbfs_header *header = (struct cbfs_header *) ptr; - // if (ntohl(header->magic) != CBFS_HEADER_MAGIC) - // printk(BIOS_ERR, "ERROR: No valid CBFS header found!\n"); - - offset = 0 - ntohl(header->romsize) + ntohl(header->offset); - int align = ntohl(header->align); - while(1) { - struct cbfs_file *file = (struct cbfs_file *) offset; - if (!cbfs_check_magic(file)) - return 0; - if (!strcmp(CBFS_NAME(file), target)) - return (unsigned long)CBFS_SUBHEADER(file); - int flen = ntohl(file->len); - int foffset = ntohl(file->offset); - unsigned long oldoffset = offset; - offset = ALIGN(offset + foffset + flen, align); - if (offset <= oldoffset) - return 0; - if (offset < 0xFFFFFFFF - ntohl(header->romsize)) - return 0; - } -} - - -static void call(unsigned long addr, unsigned long bist) -{ - asm volatile ("mov r0, %1\nbx %0\n" : : "r" (addr), "r" (bist)); -} - -static void hlt(void) +#ifdef CONFIG_BOOTBLOCK_MAINBOARD_INIT +#include CONFIG_BOOTBLOCK_MAINBOARD_INIT +#else +static void bootblock_mainboard_init(void) { - /* is there such a thing as hlt on ARM? */ - // asm volatile ("1:\n\thlt\n\tjmp 1b\n\t"); - asm volatile ("1:\nb 1b\n\t"); +#ifdef CONFIG_BOOTBLOCK_CPU_INIT + bootblock_cpu_init(); +#endif } +#endif diff --git a/src/arch/armv7/init.S b/src/arch/armv7/init.S deleted file mode 100644 index 7848581..0000000 --- a/src/arch/armv7/init.S +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Early initialization code for ARMv7 architecture. - * - * This file is based off of the OMAP3530/ARM Cortex start.S file from Das - * U-Boot, which itself got the file from armboot. - * - * Copyright (c) 2004 Texas Instruments - * Copyright (c) 2001 Marius Gr?ger - * Copyright (c) 2002 Alex Z?pke - * Copyright (c) 2002 Gary Jennejohn - * Copyright (c) 2003 Richard Woodruff - * Copyright (c) 2003 Kshitij - * Copyright (c) 2006-2008 Syed Mohammed Khasim - * Copyright (c) 2013 The Chromium OS Authors - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -.globl _start -_start: b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq -_undefined_instruction: .word _undefined_instruction -_software_interrupt: .word _software_interrupt -_prefetch_abort: .word _prefetch_abort -_data_abort: .word _data_abort -_not_used: .word _not_used -_irq: .word _irq -_fiq: .word _fiq -_pad: .word 0x12345678 /* now 16*4=64 */ - - .balignl 16,0xdeadbeef - -reset: - /* - * set the cpu to SVC32 mode - */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - msr cpsr,r0 - - /* - * From Cortex-A Series Programmer's Guide: - * Only CPU 0 performs initialization. Other CPUs go into WFI - * to do this, first work out which CPU this is - * this code typically is run before any other initialization step - */ - mrc p15, 0, r1, c0, c0, 5 @ Read Multiprocessor Affinity Register - and r1, r1, #0x3 @ Extract CPU ID bits - cmp r1, #0 - bne wait_for_interrupt @ If this is not core0, wait - - /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ - mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register - bic r0, #CR_V @ V = 0 - mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register - - /* Set vector address in CP15 VBAR register */ - ldr r0, =_start - mcr p15, 0, r0, c12, c0, 0 @Set VBAR - -/* Set stackpointer in internal RAM to call board_init_f */ -call_board_init_f: - ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) - mov sp, r0 - bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ - ldr r0,=0x00000000 - bl board_init_f - -wait_for_interrupt: - wfi - mov pc, lr @ back to my caller diff --git a/src/arch/armv7/lib/id.lds b/src/arch/armv7/lib/id.lds index 9e31ee6..22b4a02 100644 --- a/src/arch/armv7/lib/id.lds +++ b/src/arch/armv7/lib/id.lds @@ -1,5 +1,5 @@ SECTIONS { - . = (0x100000000 - CONFIG_ID_SECTION_OFFSET) - (__id_end - __id_start); + . = (0x2024000) - (__id_end - __id_start); .id (.): { *(.id) } diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig index 360c57f..6a0fe3d 100644 --- a/src/cpu/samsung/exynos5250/Kconfig +++ b/src/cpu/samsung/exynos5250/Kconfig @@ -1,6 +1,8 @@ +# FIXME: shouldn't this be 0x3400? Or maybe the bootblock in ROM needs +# to follow the BL1 image, but in SRAM it needs to be at 0x3400? Hm... config BOOTBLOCK_OFFSET hex "Bootblock offset" - default 0x3400 + default 0x2000 help This is where the Coreboot bootblock resides. For Exynos5250, this value is pre-determined by the vendor-provided BL1. diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index 1ff2327..dd2db2b 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -38,5 +38,5 @@ ramstage-$(CONFIG_SPL_BUILD) += dmc_init_ddr3.c exynos5250_add_bl1: $(obj)/coreboot.pre printf " DD Adding Samsung Exynos5250 BL1\n" - dd if=3rdparty/cpu/samsung/exynos5250/E5250.nbl1.bin \ + dd if=3rdparty/cpu/samsung/exynos5250/E5250.nbl1.30k_bl2.bin \ of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 From gerrit at coreboot.org Wed Jan 9 23:32:55 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Wed, 9 Jan 2013 23:32:55 +0100 Subject: [coreboot] Patch set updated for coreboot: 728ef24 armv7: invoke intermediate build rules References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2095 -gerrit commit 728ef24699d19147f76ca0134119a887a9e4c03e Author: David Hendricks Date: Wed Jan 2 17:48:49 2013 -0800 armv7: invoke intermediate build rules This adds $$(INTERMEDIATE) as a pre-requisite for coreboot.rom on armv7. It is modeled after the $(obj)/coreboot.rom rule for x86. Change-Id: I483a88035fa2288829b6e042e51ef932c8c4f23c Signed-off-by: David Hendricks --- src/arch/armv7/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..8176f9a 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -58,7 +58,7 @@ $(obj)/coreboot.pre1: $(CBFSTOOL) mv $(obj)/coreboot.rom $@ endif -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" cp $(obj)/coreboot.pre $@.tmp if [ -f $(objcbfs)/coreboot_ap.elf ]; \ From gerrit at coreboot.org Thu Jan 10 00:38:14 2013 From: gerrit at coreboot.org (Stefan Reinauer (stefan.reinauer@coreboot.org)) Date: Thu, 10 Jan 2013 00:38:14 +0100 Subject: [coreboot] Patch set updated for coreboot: 111c90e Implement GCC code coverage analysis References: Message-ID: Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2052 -gerrit commit 111c90e7aa9440fac75af2497d915cf6dc59032d Author: Stefan Reinauer Date: Tue Dec 18 16:23:28 2012 -0800 Implement GCC code coverage analysis In order to provide some insight on what code is executed during coreboot's run time and how well our test scenarios work, this adds code coverage support to coreboot's ram stage. This should be easily adaptable for payloads, and maybe even romstage. See http://gcc.gnu.org/onlinedocs/gcc/Gcov.html for more information. To instrument coreboot, select CONFIG_COVERAGE ("Code coverage support") in Kconfig, and recompile coreboot. coreboot will then store its code coverage information into CBMEM, if possible. Then, run "cbmem -CV" as root on the target system running the instrumented coreboot binary. This will create a whole bunch of .gcda files that contain coverage information. Tar them up, copy them to your build system machine, and untar them. Then you can use your favorite coverage utility (gcov, lcov, ...) to visualize code coverage. For a sneak peak of what will expect you, please take a look at http://www.coreboot.org/~stepan/coreboot-coverage/ Change-Id: Ib287d8309878a1f5c4be770c38b1bc0bb3aa6ec7 Signed-off-by: Stefan Reinauer --- Makefile.inc | 3 + documentation/gcov.txt | 177 ++++++ src/Kconfig | 18 + src/arch/armv7/Makefile.inc | 2 +- src/arch/armv7/coreboot_ram.ld | 8 + src/arch/x86/Makefile.inc | 2 +- src/arch/x86/boot/acpi.c | 4 + src/arch/x86/coreboot_ram.ld | 8 + src/include/cbmem.h | 1 + src/include/coverage.h | 21 + src/lib/Makefile.inc | 1 + src/lib/cbmem.c | 2 + src/lib/gcov-glue.c | 153 ++++++ src/lib/gcov-io.c | 552 +++++++++++++++++++ src/lib/gcov-io.h | 639 ++++++++++++++++++++++ src/lib/gcov-iov.h | 4 + src/lib/hardwaremain.c | 5 + src/lib/libgcov.c | 1157 ++++++++++++++++++++++++++++++++++++++++ src/lib/selfboot.c | 4 + util/cbmem/cbmem.c | 136 ++++- 20 files changed, 2888 insertions(+), 9 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index a066e25..3731797 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,6 +99,9 @@ romstage-S-ccopts:=-D__PRE_RAM__ ifeq ($(CONFIG_TRACE),y) ramstage-c-ccopts:= -finstrument-functions endif +ifeq ($(CONFIG_COVERAGE),y) +ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) diff --git a/documentation/gcov.txt b/documentation/gcov.txt new file mode 100644 index 0000000..795f827 --- /dev/null +++ b/documentation/gcov.txt @@ -0,0 +1,177 @@ +This patch contains our local modifications for gcov-io.h and libgcov.c. +The file gcov-iov.h is taken from a gcc build (produced at compile +time). The file gcov-io.c is unchanged. + +--- gcc-4.7.2/gcc/gcov-io.h 2011-12-04 10:27:19.000000000 -0800 ++++ coreboot/src/lib/gcov-io.h 2013-01-09 15:29:19.000000000 -0800 +@@ -163,6 +163,24 @@ + #ifndef GCC_GCOV_IO_H + #define GCC_GCOV_IO_H + ++#ifdef __COREBOOT__ ++#define GCOV_LINKAGE /* nothing */ ++/* We need the definitions for ++ BITS_PER_UNIT and ++ LONG_LONG_TYPE_SIZE ++ They are defined in gcc/defaults.h and gcc/config/ ++ (like, gcc/config/i386/i386.h). And it can be overridden by setting ++ in build scripts. Here I hardcoded the value for x86. */ ++#define BITS_PER_UNIT 8 ++#define LONG_LONG_TYPE_SIZE 64 ++ ++/* There are many gcc_assertions. Set the vaule to 1 if we want a warning ++ message if the assertion fails. */ ++#ifndef ENABLE_ASSERT_CHECKING ++#define ENABLE_ASSERT_CHECKING 1 ++#endif ++#endif /* __COREBOOT__ */ ++ + #if IN_LIBGCOV + /* About the target */ + +@@ -232,7 +250,9 @@ + is not also used in a DSO. */ + #if IN_LIBGCOV + ++#ifndef __COREBOOT__ + #include "tconfig.h" ++#endif /* __COREBOOT__ */ + + #define gcov_var __gcov_var + #define gcov_open __gcov_open +@@ -455,8 +475,10 @@ + /* Register a new object file module. */ + extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + ++#ifndef __COREBOOT__ + /* Called before fork, to avoid double counting. */ + extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; ++#endif + + /* The merge function that just sums the counters. */ + extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; +--- gcc-4.7.2/libgcc/libgcov.c 2012-01-11 10:50:21.000000000 -0800 ++++ coreboot/src/lib/libgcov.c 2013-01-09 15:32:37.000000000 -0800 +@@ -25,12 +25,41 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + ++#define __COREBOOT__ ++#ifdef __COREBOOT__ ++#include ++#include ++#include ++#include ++typedef s32 pid_t; ++#define gcc_assert(x) ASSERT(x) ++#define fprintf(file, x...) printk(BIOS_ERR, x) ++#define alloca(size) __builtin_alloca (size) ++#include "gcov-glue.c" ++ ++/* Define MACROs to be used by coreboot compilation. */ ++# define L_gcov ++# define L_gcov_interval_profiler ++# define L_gcov_pow2_profiler ++# define L_gcov_one_value_profiler ++# define L_gcov_indirect_call_profiler ++# define L_gcov_average_profiler ++# define L_gcov_ior_profiler ++ ++# define HAVE_CC_TLS 0 ++# define __GCOV_KERNEL__ ++ ++# define IN_LIBGCOV 1 ++# define IN_GCOV 0 ++#else /* __COREBOOT__ */ + #include "tconfig.h" + #include "tsystem.h" + #include "coretypes.h" + #include "tm.h" + #include "libgcc_tm.h" ++#endif /* __COREBOOT__ */ + ++#ifndef __COREBOOT__ + #if defined(inhibit_libc) + #define IN_LIBGCOV (-1) + #else +@@ -41,6 +70,7 @@ + #define GCOV_LINKAGE /* nothing */ + #endif + #endif ++#endif /* __COREBOOT__ */ + #include "gcov-io.h" + + #if defined(inhibit_libc) +@@ -68,12 +98,17 @@ + + #else + ++#ifndef __COREBOOT__ + #include + #if GCOV_LOCKED + #include + #include + #include + #endif ++#else ++void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), ++ unsigned n_counters __attribute__ ((unused))) {} ++#endif /* __COREBOOT__ */ + + #ifdef L_gcov + #include "gcov-io.c" +@@ -99,6 +134,10 @@ + static int + create_file_directory (char *filename) + { ++#ifdef __COREBOOT__ ++ (void) filename; ++ return 0; ++#else + #if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +@@ -137,6 +176,7 @@ + }; + return 0; + #endif ++#endif + } + + static struct gcov_fn_buffer * +@@ -279,7 +319,7 @@ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; +- int f_ix; ++ int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; +@@ -329,6 +369,7 @@ + } + } + ++#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); +@@ -352,6 +393,7 @@ + prefix_length--; + } + else ++#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume +@@ -696,8 +738,10 @@ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + ++#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); ++#endif + + info->next = gcov_list; + gcov_list = info; diff --git a/src/Kconfig b/src/Kconfig index 0a94ed8..2c97327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,15 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail. +config COVERAGE + bool "Code coverage support" + depends on COMPILER_GCC + default n + help + Add code coverage support for coreboot. This will store code + coverage information in CBMEM for extraction from user space. + If unsure, say N. + endmenu source src/mainboard/Kconfig @@ -868,6 +877,15 @@ config TRACE the 0xaaaabbbb is the actual function and 0xccccdddd is EIP of calling function. Please note some printk releated functions are omitted from trace to have good looking console dumps. + +config DEBUG_COVERAGE + bool "Debug code coverage" + default n + depends on COVERAGE + help + If enabled, the code coverage hooks in coreboot will output some + information about the coverage data that is dumped. + endmenu # These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc index d7fbbdf..4a836d1 100644 --- a/src/arch/armv7/Makefile.inc +++ b/src/arch/armv7/Makefile.inc @@ -121,7 +121,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m -m armelf_linux_eabi -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --wrap __uidiv --wrap __do_div64 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/armv7/coreboot_ram.ld b/src/arch/armv7/coreboot_ram.ld index 57ddd03..329bce4 100644 --- a/src/arch/armv7/coreboot_ram.ld +++ b/src/arch/armv7/coreboot_ram.ld @@ -38,6 +38,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index e84700e..ea86f8f 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -166,7 +166,7 @@ $(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group else - $(CC) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group + $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group endif ################################################################################ diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 1d7dbf8..730e53e 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -36,6 +36,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -642,6 +643,9 @@ void suspend_resume(void) /* Call mainboard resume handler first, if defined. */ if (mainboard_suspend_resume) mainboard_suspend_resume(); +#if CONFIG_COVERAGE + coverage_exit(); +#endif post_code(POST_OS_RESUME); acpi_jump_to_wakeup(wake_vec); } diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld index a87a0e7..7ce0367 100644 --- a/src/arch/x86/coreboot_ram.ld +++ b/src/arch/x86/coreboot_ram.ld @@ -39,6 +39,14 @@ SECTIONS _etext = .; } + .ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + *(.ctors); + LONG(0); + __CTOR_END__ = .; + } + .rodata : { _rodata = .; . = ALIGN(4); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 21efe77..08e913a 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -55,6 +55,7 @@ #define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_COVERAGE 0x47434f56 #define CBMEM_ID_NONE 0x00000000 #ifndef __ASSEMBLER__ diff --git a/src/include/coverage.h b/src/include/coverage.h new file mode 100644 index 0000000..e1c50c5 --- /dev/null +++ b/src/include/coverage.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void coverage_init(void); +void coverage_exit(void); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6b3f0d8..6796448 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -70,6 +70,7 @@ ramstage-$(CONFIG_USBDEBUG) += usbdebug.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index 7378d8c..f270f5d 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -260,6 +260,8 @@ void cbmem_list(void) case CBMEM_ID_TIMESTAMP: printk(BIOS_DEBUG, "TIME STAMP "); break; case CBMEM_ID_MRCDATA: printk(BIOS_DEBUG, "MRC DATA "); break; case CBMEM_ID_CONSOLE: printk(BIOS_DEBUG, "CONSOLE "); break; + case CBMEM_ID_ELOG: printk(BIOS_DEBUG, "ELOG "); break; + case CBMEM_ID_COVERAGE: printk(BIOS_DEBUG, "COVERAGE "); break; default: printk(BIOS_DEBUG, "%08x ", cbmem_toc[i].id); } printk(BIOS_DEBUG, "%08llx ", cbmem_toc[i].base); diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c new file mode 100644 index 0000000..7c069cb --- /dev/null +++ b/src/lib/gcov-glue.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +typedef struct file { + uint32_t magic; + struct file *next; + char *filename; + char *data; + int offset; + int len; +} FILE; + +#define SEEK_SET 0 /* Seek from beginning of file. */ + +#define DIR_SEPARATOR '/' +#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#define HAS_DRIVE_SPEC(f) (0) + +#define COVERAGE_SIZE (32*1024) + +static FILE *current_file = NULL; +static FILE *previous_file = NULL; + +static FILE *fopen(const char *path, const char *mode) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fopen %s with mode %s\n", + path, mode); +#endif + if (!current_file) { + current_file = cbmem_add(CBMEM_ID_COVERAGE, 32*1024); + } else { + previous_file = current_file; + current_file = (FILE *)(ALIGN(((unsigned long)previous_file->data + previous_file->len), 16)); + } + + // TODO check if we're at the end of the CBMEM region (ENOMEM) + if (current_file) { + current_file->magic = 0x584d4153; + current_file->next = NULL; + if (previous_file) + previous_file->next = current_file; + current_file->filename = (char *)¤t_file[1]; + strcpy(current_file->filename, path); + current_file->data = (char *)ALIGN(((unsigned long)current_file->filename + strlen(path) + 1), 16); + current_file->offset = 0; + current_file->len = 0; + } + + return current_file; +} + +static int fclose(FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fclose %s\n", stream->filename); +#endif + return 0; +} + +static int fseek(FILE *stream, long offset, int whence) +{ + /* fseek should only be called with offset==0 and whence==SEEK_SET + * to a freshly opened file. */ + gcc_assert (offset == 0 && whence == SEEK_SET); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fseek %s offset=%d whence=%d\n", + stream->filename, offset, whence); +#endif + return 0; +} + +static long ftell(FILE *stream) +{ + /* ftell should currently not be called */ + gcc_assert(0); +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "ftell %s\n", stream->filename); +#endif + return 0; +} + +static size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fread: ptr=%p size=%zd nmemb=%zd FILE*=%p\n", + ptr, size, nmemb, stream); +#endif + return 0; +} + +static size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "fwrite: %zd * 0x%zd bytes to file %s\n", + nmemb, size, stream->filename); +#endif + // TODO check if file is last opened file and fail otherwise. + + memcpy(stream->data + stream->offset, ptr, size * nmemb); + stream->len += (nmemb * size) - (stream->len - stream->offset); + stream->offset += nmemb * size; + return nmemb; +} + +static void setbuf(FILE *stream, char *buf) +{ + gcc_assert(buf == 0); +} + +void coverage_init(void) +{ + extern long __CTOR_LIST__; + typedef void (*func_ptr)(void) ; + func_ptr *ctor = (func_ptr*) &__CTOR_LIST__; + if (ctor == NULL) + return; + + for ( ; *ctor != (func_ptr) 0; ctor++) { + (*ctor)(); + } +} + +void __gcov_flush(void); +void coverage_exit(void) +{ +#if CONFIG_DEBUG_COVERAGE + printk(BIOS_DEBUG, "Syncing coverage data.\n"); +#endif + __gcov_flush(); +} + + diff --git a/src/lib/gcov-io.c b/src/lib/gcov-io.c new file mode 100644 index 0000000..37c1c3e --- /dev/null +++ b/src/lib/gcov-io.c @@ -0,0 +1,552 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007, + 2008 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Routines declared in gcov-io.h. This file should be #included by + another source file, after having #included gcov-io.h. */ + +#if !IN_GCOV +static void gcov_write_block (unsigned); +static gcov_unsigned_t *gcov_write_words (unsigned); +#endif +static const gcov_unsigned_t *gcov_read_words (unsigned); +#if !IN_LIBGCOV +static void gcov_allocate (unsigned); +#endif + +static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +{ +#if !IN_LIBGCOV + if (gcov_var.endian) + { + value = (value >> 16) | (value << 16); + value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); + } +#endif + return value; +} + +/* Open a gcov file. NAME is the name of the file to open and MODE + indicates whether a new file should be created, or an existing file + opened. If MODE is >= 0 an existing file will be opened, if + possible, and if MODE is <= 0, a new file will be created. Use + MODE=0 to attempt to reopen an existing file and then fall back on + creating a new one. If MODE < 0, the file will be opened in + read-only mode. Otherwise it will be opened for modification. + Return zero on failure, >0 on opening an existing file and <0 on + creating a new one. */ + +GCOV_LINKAGE int +#if IN_LIBGCOV +gcov_open (const char *name) +#else +gcov_open (const char *name, int mode) +#endif +{ +#if IN_LIBGCOV + const int mode = 0; +#endif +#if GCOV_LOCKED + struct flock s_flock; + int fd; + + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif + + gcc_assert (!gcov_var.file); + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; +#if !IN_LIBGCOV + gcov_var.endian = 0; +#endif +#if GCOV_LOCKED + if (mode > 0) + { + /* Read-only mode - acquire a read-lock. */ + s_flock.l_type = F_RDLCK; + fd = open (name, O_RDONLY); + } + else + { + /* Write mode - acquire a write-lock. */ + s_flock.l_type = F_WRLCK; + fd = open (name, O_RDWR | O_CREAT, 0666); + } + if (fd < 0) + return 0; + + while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) + continue; + + gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); + + if (!gcov_var.file) + { + close (fd); + return 0; + } + + if (mode > 0) + gcov_var.mode = 1; + else if (mode == 0) + { + struct stat st; + + if (fstat (fd, &st) < 0) + { + fclose (gcov_var.file); + gcov_var.file = 0; + return 0; + } + if (st.st_size != 0) + gcov_var.mode = 1; + else + gcov_var.mode = mode * 2 + 1; + } + else + gcov_var.mode = mode * 2 + 1; +#else + if (mode >= 0) + gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + + if (gcov_var.file) + gcov_var.mode = 1; + else if (mode <= 0) + { + gcov_var.file = fopen (name, "w+b"); + if (gcov_var.file) + gcov_var.mode = mode * 2 + 1; + } + if (!gcov_var.file) + return 0; +#endif + + setbuf (gcov_var.file, (char *)0); + + return 1; +} + +/* Close the current gcov file. Flushes data to disk. Returns nonzero + on failure or error flag set. */ + +GCOV_LINKAGE int +gcov_close (void) +{ + if (gcov_var.file) + { +#if !IN_GCOV + if (gcov_var.offset && gcov_var.mode < 0) + gcov_write_block (gcov_var.offset); +#endif + fclose (gcov_var.file); + gcov_var.file = 0; + gcov_var.length = 0; + } +#if !IN_LIBGCOV + free (gcov_var.buffer); + gcov_var.alloc = 0; + gcov_var.buffer = 0; +#endif + gcov_var.mode = 0; + return gcov_var.error; +} + +#if !IN_LIBGCOV +/* Check if MAGIC is EXPECTED. Use it to determine endianness of the + file. Returns +1 for same endian, -1 for other endian and zero for + not EXPECTED. */ + +GCOV_LINKAGE int +gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) +{ + if (magic == expected) + return 1; + magic = (magic >> 16) | (magic << 16); + magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); + if (magic == expected) + { + gcov_var.endian = 1; + return -1; + } + return 0; +} +#endif + +#if !IN_LIBGCOV +static void +gcov_allocate (unsigned length) +{ + size_t new_size = gcov_var.alloc; + + if (!new_size) + new_size = GCOV_BLOCK_SIZE; + new_size += length; + new_size *= 2; + + gcov_var.alloc = new_size; + gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); +} +#endif + +#if !IN_GCOV +/* Write out the current block, if needs be. */ + +static void +gcov_write_block (unsigned size) +{ + if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + gcov_var.error = 1; + gcov_var.start += size; + gcov_var.offset -= size; +} + +/* Allocate space to write BYTES bytes to the gcov file. Return a + pointer to those bytes, or NULL on failure. */ + +static gcov_unsigned_t * +gcov_write_words (unsigned words) +{ + gcov_unsigned_t *result; + + gcc_assert (gcov_var.mode < 0); +#if IN_LIBGCOV + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + { + gcov_write_block (GCOV_BLOCK_SIZE); + if (gcov_var.offset) + { + gcc_assert (gcov_var.offset == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); + } + } +#else + if (gcov_var.offset + words > gcov_var.alloc) + gcov_allocate (gcov_var.offset + words); +#endif + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + + return result; +} + +/* Write unsigned VALUE to coverage file. Sets error flag + appropriately. */ + +GCOV_LINKAGE void +gcov_write_unsigned (gcov_unsigned_t value) +{ + gcov_unsigned_t *buffer = gcov_write_words (1); + + buffer[0] = value; +} + +/* Write counter VALUE to coverage file. Sets error flag + appropriately. */ + +#if IN_LIBGCOV +GCOV_LINKAGE void +gcov_write_counter (gcov_type value) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = (gcov_unsigned_t) value; + if (sizeof (value) > sizeof (gcov_unsigned_t)) + buffer[1] = (gcov_unsigned_t) (value >> 32); + else + buffer[1] = 0; +} +#endif /* IN_LIBGCOV */ + +#if !IN_LIBGCOV +/* Write STRING to coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE void +gcov_write_string (const char *string) +{ + unsigned length = 0; + unsigned alloc = 0; + gcov_unsigned_t *buffer; + + if (string) + { + length = strlen (string); + alloc = (length + 4) >> 2; + } + + buffer = gcov_write_words (1 + alloc); + + buffer[0] = alloc; + buffer[alloc] = 0; + memcpy (&buffer[1], string, length); +} +#endif + +#if !IN_LIBGCOV +/* Write a tag TAG and reserve space for the record length. Return a + value to be used for gcov_write_length. */ + +GCOV_LINKAGE gcov_position_t +gcov_write_tag (gcov_unsigned_t tag) +{ + gcov_position_t result = gcov_var.start + gcov_var.offset; + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = 0; + + return result; +} + +/* Write a record length using POSITION, which was returned by + gcov_write_tag. The current file position is the end of the + record, and is restored before returning. Returns nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_length (gcov_position_t position) +{ + unsigned offset; + gcov_unsigned_t length; + gcov_unsigned_t *buffer; + + gcc_assert (gcov_var.mode < 0); + gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); + gcc_assert (position >= gcov_var.start); + offset = position - gcov_var.start; + length = gcov_var.offset - offset - 2; + buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; + buffer[1] = length; + if (gcov_var.offset >= GCOV_BLOCK_SIZE) + gcov_write_block (gcov_var.offset); +} + +#else /* IN_LIBGCOV */ + +/* Write a tag TAG and length LENGTH. */ + +GCOV_LINKAGE void +gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) +{ + gcov_unsigned_t *buffer = gcov_write_words (2); + + buffer[0] = tag; + buffer[1] = length; +} + +/* Write a summary structure to the gcov file. Return nonzero on + overflow. */ + +GCOV_LINKAGE void +gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) +{ + unsigned ix; + const struct gcov_ctr_summary *csum; + + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); + gcov_write_unsigned (summary->checksum); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + gcov_write_unsigned (csum->num); + gcov_write_unsigned (csum->runs); + gcov_write_counter (csum->sum_all); + gcov_write_counter (csum->run_max); + gcov_write_counter (csum->sum_max); + } +} +#endif /* IN_LIBGCOV */ + +#endif /*!IN_GCOV */ + +/* Return a pointer to read BYTES bytes from the gcov file. Returns + NULL on failure (read past EOF). */ + +static const gcov_unsigned_t * +gcov_read_words (unsigned words) +{ + const gcov_unsigned_t *result; + unsigned excess = gcov_var.length - gcov_var.offset; + + gcc_assert (gcov_var.mode > 0); + if (excess < words) + { + gcov_var.start += gcov_var.offset; +#if IN_LIBGCOV + if (excess) + { + gcc_assert (excess == 1); + memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); + } +#else + memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); +#endif + gcov_var.offset = 0; + gcov_var.length = excess; +#if IN_LIBGCOV + gcc_assert (!gcov_var.length || gcov_var.length == 1); + excess = GCOV_BLOCK_SIZE; +#else + if (gcov_var.length + words > gcov_var.alloc) + gcov_allocate (gcov_var.length + words); + excess = gcov_var.alloc - gcov_var.length; +#endif + excess = fread (gcov_var.buffer + gcov_var.length, + 1, excess << 2, gcov_var.file) >> 2; + gcov_var.length += excess; + if (gcov_var.length < words) + { + gcov_var.overread += words - gcov_var.length; + gcov_var.length = 0; + return 0; + } + } + result = &gcov_var.buffer[gcov_var.offset]; + gcov_var.offset += words; + return result; +} + +/* Read unsigned value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_unsigned (void) +{ + gcov_unsigned_t value; + const gcov_unsigned_t *buffer = gcov_read_words (1); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + return value; +} + +/* Read counter value from a coverage file. Sets error flag on file + error, overflow flag on overflow */ + +GCOV_LINKAGE gcov_type +gcov_read_counter (void) +{ + gcov_type value; + const gcov_unsigned_t *buffer = gcov_read_words (2); + + if (!buffer) + return 0; + value = from_file (buffer[0]); + if (sizeof (value) > sizeof (gcov_unsigned_t)) + value |= ((gcov_type) from_file (buffer[1])) << 32; + else if (buffer[1]) + gcov_var.error = -1; + + return value; +} + +/* Read string from coverage file. Returns a pointer to a static + buffer, or NULL on empty string. You must copy the string before + calling another gcov function. */ + +#if !IN_LIBGCOV +GCOV_LINKAGE const char * +gcov_read_string (void) +{ + unsigned length = gcov_read_unsigned (); + + if (!length) + return 0; + + return (const char *) gcov_read_words (length); +} +#endif + +GCOV_LINKAGE void +gcov_read_summary (struct gcov_summary *summary) +{ + unsigned ix; + struct gcov_ctr_summary *csum; + + summary->checksum = gcov_read_unsigned (); + for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) + { + csum->num = gcov_read_unsigned (); + csum->runs = gcov_read_unsigned (); + csum->sum_all = gcov_read_counter (); + csum->run_max = gcov_read_counter (); + csum->sum_max = gcov_read_counter (); + } +} + +#if !IN_LIBGCOV +/* Reset to a known position. BASE should have been obtained from + gcov_position, LENGTH should be a record length. */ + +GCOV_LINKAGE void +gcov_sync (gcov_position_t base, gcov_unsigned_t length) +{ + gcc_assert (gcov_var.mode > 0); + base += length; + if (base - gcov_var.start <= gcov_var.length) + gcov_var.offset = base - gcov_var.start; + else + { + gcov_var.offset = gcov_var.length = 0; + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; + } +} +#endif + +#if IN_LIBGCOV +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + gcc_assert (gcov_var.mode < 0); + if (gcov_var.offset) + gcov_write_block (gcov_var.offset); + fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = ftell (gcov_var.file) >> 2; +} +#endif + +#if IN_GCOV > 0 +/* Return the modification time of the current gcov file. */ + +GCOV_LINKAGE time_t +gcov_time (void) +{ + struct stat status; + + if (fstat (fileno (gcov_var.file), &status)) + return 0; + else + return status.st_mtime; +} +#endif /* IN_GCOV */ diff --git a/src/lib/gcov-io.h b/src/lib/gcov-io.h new file mode 100644 index 0000000..4502bd6 --- /dev/null +++ b/src/lib/gcov-io.h @@ -0,0 +1,639 @@ +/* File format for coverage information + Copyright (C) 1996, 1997, 1998, 2000, 2002, + 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. + Contributed by Bob Manson . + Completely remangled by Nathan Sidwell . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + + +/* Coverage information is held in two files. A notes file, which is + generated by the compiler, and a data file, which is generated by + the program under test. Both files use a similar structure. We do + not attempt to make these files backwards compatible with previous + versions, as you only need coverage information when developing a + program. We do hold version information, so that mismatches can be + detected, and we use a format that allows tools to skip information + they do not understand or are not interested in. + + Numbers are recorded in the 32 bit unsigned binary form of the + endianness of the machine generating the file. 64 bit numbers are + stored as two 32 bit numbers, the low part first. Strings are + padded with 1 to 4 NUL bytes, to bring the length up to a multiple + of 4. The number of 4 bytes is stored, followed by the padded + string. Zero length and NULL strings are simply stored as a length + of zero (they have no trailing NUL or padding). + + int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3 + int64: int32:low int32:high + string: int32:0 | int32:length char* char:0 padding + padding: | char:0 | char:0 char:0 | char:0 char:0 char:0 + item: int32 | int64 | string + + The basic format of the files is + + file : int32:magic int32:version int32:stamp record* + + The magic ident is different for the notes and the data files. The + magic ident is used to determine the endianness of the file, when + reading. The version is the same for both files and is derived + from gcc's version number. The stamp value is used to synchronize + note and data files and to synchronize merging within a data + file. It need not be an absolute time stamp, merely a ticker that + increments fast enough and cycles slow enough to distinguish + different compile/run/compile cycles. + + Although the ident and version are formally 32 bit numbers, they + are derived from 4 character ASCII strings. The version number + consists of the single character major version number, a two + character minor version number (leading zero for versions less than + 10), and a single character indicating the status of the release. + That will be 'e' experimental, 'p' prerelease and 'r' for release. + Because, by good fortune, these are in alphabetical order, string + collating can be used to compare version strings. Be aware that + the 'e' designation will (naturally) be unstable and might be + incompatible with itself. For gcc 3.4 experimental, it would be + '304e' (0x33303465). When the major version reaches 10, the + letters A-Z will be used. Assuming minor increments releases every + 6 months, we have to make a major increment every 50 years. + Assuming major increments releases every 5 years, we're ok for the + next 155 years -- good enough for me. + + A record has a tag, length and variable amount of data. + + record: header data + header: int32:tag int32:length + data: item* + + Records are not nested, but there is a record hierarchy. Tag + numbers reflect this hierarchy. Tags are unique across note and + data files. Some record types have a varying amount of data. The + LENGTH is the number of 4bytes that follow and is usually used to + determine how much data. The tag value is split into 4 8-bit + fields, one for each of four possible levels. The most significant + is allocated first. Unused levels are zero. Active levels are + odd-valued, so that the LSB of the level is one. A sub-level + incorporates the values of its superlevels. This formatting allows + you to determine the tag hierarchy, without understanding the tags + themselves, and is similar to the standard section numbering used + in technical documents. Level values [1..3f] are used for common + tags, values [41..9f] for the notes file and [a1..ff] for the data + file. + + The basic block graph file contains the following records + note: unit function-graph* + unit: header int32:checksum string:source + function-graph: announce_function basic_blocks {arcs | lines}* + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + string:name string:source int32:lineno + basic_block: header int32:flags* + arcs: header int32:block_no arc* + arc: int32:dest_block int32:flags + lines: header int32:block_no line* + int32:0 string:NULL + line: int32:line_no | int32:0 string:filename + + The BASIC_BLOCK record holds per-bb flags. The number of blocks + can be inferred from its data length. There is one ARCS record per + basic block. The number of arcs from a bb is implicit from the + data length. It enumerates the destination bb and per-arc flags. + There is one LINES record per basic block, it enumerates the source + lines which belong to that basic block. Source file names are + introduced by a line number of 0, following lines are from the new + source file. The initial source file for the function is NULL, but + the current source file should be remembered from one LINES record + to the next. The end of a block is indicated by an empty filename + - this does not reset the current source file. Note there is no + ordering of the ARCS and LINES records: they may be in any order, + interleaved in any manner. The current filename follows the order + the LINES records are stored in the file, *not* the ordering of the + blocks they are for. + + The data file contains the following records. + data: {unit summary:object summary:program* function-data*}* + unit: header int32:checksum + function-data: announce_function present counts + announce_function: header int32:ident + int32:lineno_checksum int32:cfg_checksum + present: header int32:present + counts: header int64:count* + summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE + count-summary: int32:num int32:runs int64:sum + int64:max int64:sum_max + + The ANNOUNCE_FUNCTION record is the same as that in the note file, + but without the source location. The COUNTS gives the + counter values for instrumented features. The about the whole + program. The checksum is used for whole program summaries, and + disambiguates different programs which include the same + instrumented object file. There may be several program summaries, + each with a unique checksum. The object summary's checksum is + zero. Note that the data file might contain information from + several runs concatenated, or the data might be merged. + + This file is included by both the compiler, gcov tools and the + runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to + distinguish which case is which. If IN_LIBGCOV is nonzero, + libgcov is being built. If IN_GCOV is nonzero, the gcov tools are + being built. Otherwise the compiler is being built. IN_GCOV may be + positive or negative. If positive, we are compiling a tool that + requires additional functions (see the code for knowledge of what + those functions are). */ + +#ifndef GCC_GCOV_IO_H +#define GCC_GCOV_IO_H + +#ifdef __COREBOOT__ +#define GCOV_LINKAGE /* nothing */ +/* We need the definitions for + BITS_PER_UNIT and + LONG_LONG_TYPE_SIZE + They are defined in gcc/defaults.h and gcc/config/ + (like, gcc/config/i386/i386.h). And it can be overridden by setting + in build scripts. Here I hardcoded the value for x86. */ +#define BITS_PER_UNIT 8 +#define LONG_LONG_TYPE_SIZE 64 + +/* There are many gcc_assertions. Set the vaule to 1 if we want a warning + message if the assertion fails. */ +#ifndef ENABLE_ASSERT_CHECKING +#define ENABLE_ASSERT_CHECKING 1 +#endif +#endif /* __COREBOOT__ */ + +#if IN_LIBGCOV +/* About the target */ + +#if BITS_PER_UNIT == 8 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef unsigned gcov_position_t __attribute__ ((mode (SI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (DI))); +#else +typedef signed gcov_type __attribute__ ((mode (SI))); +#endif +#else +#if BITS_PER_UNIT == 16 +typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); +typedef unsigned gcov_position_t __attribute__ ((mode (HI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (SI))); +#else +typedef signed gcov_type __attribute__ ((mode (HI))); +#endif +#else +typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); +typedef unsigned gcov_position_t __attribute__ ((mode (QI))); +#if LONG_LONG_TYPE_SIZE > 32 +typedef signed gcov_type __attribute__ ((mode (HI))); +#else +typedef signed gcov_type __attribute__ ((mode (QI))); +#endif +#endif +#endif + + +#if defined (TARGET_POSIX_IO) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#else /* !IN_LIBGCOV */ +/* About the host */ + +typedef unsigned gcov_unsigned_t; +typedef unsigned gcov_position_t; +/* gcov_type is typedef'd elsewhere for the compiler */ +#if IN_GCOV +#define GCOV_LINKAGE static +typedef HOST_WIDEST_INT gcov_type; +#if IN_GCOV > 0 +#include +#endif +#else /*!IN_GCOV */ +#define GCOV_TYPE_SIZE (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32) +#endif + +#if defined (HOST_HAS_F_SETLKW) +#define GCOV_LOCKED 1 +#else +#define GCOV_LOCKED 0 +#endif + +#endif /* !IN_LIBGCOV */ + +/* In gcov we want function linkage to be static. In the compiler we want + it extern, so that they can be accessed from elsewhere. In libgcov we + need these functions to be extern, so prefix them with __gcov. In + libgcov they must also be hidden so that the instance in the executable + is not also used in a DSO. */ +#if IN_LIBGCOV + +#ifndef __COREBOOT__ +#include "tconfig.h" +#endif /* __COREBOOT__ */ + +#define gcov_var __gcov_var +#define gcov_open __gcov_open +#define gcov_close __gcov_close +#define gcov_write_tag_length __gcov_write_tag_length +#define gcov_position __gcov_position +#define gcov_seek __gcov_seek +#define gcov_rewrite __gcov_rewrite +#define gcov_is_error __gcov_is_error +#define gcov_write_unsigned __gcov_write_unsigned +#define gcov_write_counter __gcov_write_counter +#define gcov_write_summary __gcov_write_summary +#define gcov_read_unsigned __gcov_read_unsigned +#define gcov_read_counter __gcov_read_counter +#define gcov_read_summary __gcov_read_summary + +/* Poison these, so they don't accidentally slip in. */ +#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length +#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#else + +#define ATTRIBUTE_HIDDEN + +#endif + +#ifndef GCOV_LINKAGE +#define GCOV_LINKAGE extern +#endif + +/* File suffixes. */ +#define GCOV_DATA_SUFFIX ".gcda" +#define GCOV_NOTE_SUFFIX ".gcno" + +/* File magic. Must not be palindromes. */ +#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ +#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */ + +/* gcov-iov.h is automatically generated by the makefile from + version.c, it looks like + #define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef) +*/ +#include "gcov-iov.h" + +/* Convert a magic or version number to a 4 character string. */ +#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ + ((ARRAY)[0] = (char)((VALUE) >> 24), \ + (ARRAY)[1] = (char)((VALUE) >> 16), \ + (ARRAY)[2] = (char)((VALUE) >> 8), \ + (ARRAY)[3] = (char)((VALUE) >> 0)) + +/* The record tags. Values [1..3f] are for tags which may be in either + file. Values [41..9f] for those in the note file and [a1..ff] for + the data file. The tag value zero is used as an explicit end of + file marker -- it is not required to be present. */ + +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) +#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) +#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) +#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) +#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_SUMMARY_LENGTH \ + (1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2)) + +/* Counters that are collected. */ +#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ +#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be + summaried. */ +#define GCOV_FIRST_VALUE_COUNTER 1 /* The first of counters used for value + profiling. They must form a consecutive + interval and their order must match + the order of HIST_TYPEs in + value-prof.h. */ +#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */ +#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm + of a value. */ +#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */ +#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between + consecutive values of expression. */ + +#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */ +#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the + counter. */ +#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to + counter. */ +#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value + profiling. */ +#define GCOV_COUNTERS 8 + +/* Number of counters used for value profiling. */ +#define GCOV_N_VALUE_COUNTERS \ + (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) + + /* A list of human readable names of the counters */ +#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \ + "delta", "indirect_call", "average", "ior"} + + /* Names of merge functions for counters. */ +#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_add", \ + "__gcov_merge_single", \ + "__gcov_merge_delta", \ + "__gcov_merge_single", \ + "__gcov_merge_add", \ + "__gcov_merge_ior"} + +/* Convert a counter index to a tag. */ +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) +/* Convert a tag to a counter. */ +#define GCOV_COUNTER_FOR_TAG(TAG) \ + ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)) +/* Check whether a tag is a counter tag. */ +#define GCOV_TAG_IS_COUNTER(TAG) \ + (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) + +/* The tag level mask has 1's in the position of the inner levels, & + the lsb of the current level, and zero on the current and outer + levels. */ +#define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG)) + +/* Return nonzero if SUB is an immediate subtag of TAG. */ +#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \ + && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG))) + +/* Return nonzero if SUB is at a sublevel to TAG. */ +#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \ + (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB)) + +/* Basic block flags. */ +#define GCOV_BLOCK_UNEXPECTED (1 << 1) + +/* Arc flags. */ +#define GCOV_ARC_ON_TREE (1 << 0) +#define GCOV_ARC_FAKE (1 << 1) +#define GCOV_ARC_FALLTHROUGH (1 << 2) + +/* Structured records. */ + +/* Cumulative counter data. */ +struct gcov_ctr_summary +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_unsigned_t runs; /* number of program runs */ + gcov_type sum_all; /* sum of all counters accumulated. */ + gcov_type run_max; /* maximum value on a single run. */ + gcov_type sum_max; /* sum of individual run max values. */ +}; + +/* Object & program summary record. */ +struct gcov_summary +{ + gcov_unsigned_t checksum; /* checksum of program */ + struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; +}; + +/* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ + +#if IN_LIBGCOV +/* Information about counters for a single function. */ +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ +}; + +/* Information about a single function. This uses the trailing array + idiom. The number of counters is determined from the merge pointer + array in gcov_info. The key is used to detect which of a set of + comdat functions was selected -- it points to the gcov_info object + of the object file containing the selected comdat function. */ + +struct gcov_fn_info +{ + const struct gcov_info *key; /* comdat key */ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ + gcov_unsigned_t cfg_checksum; /* function cfg checksum */ + struct gcov_ctr_info ctrs[0]; /* instrumented counters */ +}; + +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; /* output file name */ + + gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for + unused) */ + + unsigned n_functions; /* number of functions */ + const struct gcov_fn_info *const *functions; /* pointer to pointers + to function information */ +}; + +/* Register a new object file module. */ +extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; + +#ifndef __COREBOOT__ +/* Called before fork, to avoid double counting. */ +extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; +#endif + +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common value. */ +extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function to choose the most common difference between + consecutive values. */ +extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The merge function that just ors the counters together. */ +extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; + +/* The profiler functions. */ +extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); +extern void __gcov_pow2_profiler (gcov_type *, gcov_type); +extern void __gcov_one_value_profiler (gcov_type *, gcov_type); +extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *); +extern void __gcov_average_profiler (gcov_type *, gcov_type); +extern void __gcov_ior_profiler (gcov_type *, gcov_type); + +#ifndef inhibit_libc +/* The wrappers around some library functions.. */ +extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; +extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; +extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; +extern int __gcov_execve (const char *, char *const [], char *const []) + ATTRIBUTE_HIDDEN; +#endif + +#endif /* IN_LIBGCOV */ + +#if IN_LIBGCOV >= 0 + +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var ATTRIBUTE_HIDDEN; + +/* Functions for reading and writing gcov files. In libgcov you can + open the file for reading then writing. Elsewhere you can open the + file either for reading or for writing. When reading a file you may + use the gcov_read_* functions, gcov_sync, gcov_position, & + gcov_error. When writing a file you may use the gcov_write + functions, gcov_seek & gcov_error. When a file is to be rewritten + you use the functions for reading, then gcov_rewrite then the + functions for writing. Your file may become corrupted if you break + these invariants. */ +#if IN_LIBGCOV +GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; +#else +GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); +GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); +#endif +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; + +/* Available everywhere. */ +static gcov_position_t gcov_position (void); +static int gcov_is_error (void); + +GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; + +#if IN_LIBGCOV +/* Available only in libgcov */ +GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, + const struct gcov_summary *) + ATTRIBUTE_HIDDEN; +static void gcov_rewrite (void); +GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; +#else +/* Available outside libgcov */ +GCOV_LINKAGE const char *gcov_read_string (void); +GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, + gcov_unsigned_t /*length */); +#endif + +#if !IN_GCOV +/* Available outside gcov */ +GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +#endif + +#if !IN_GCOV && !IN_LIBGCOV +/* Available only in compiler */ +GCOV_LINKAGE void gcov_write_string (const char *); +GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); +GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); +#endif + +#if IN_GCOV > 0 +/* Available in gcov */ +GCOV_LINKAGE time_t gcov_time (void); +#endif + +/* Save the current position in the gcov file. */ + +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ + +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ + +static inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + +#endif /* IN_LIBGCOV >= 0 */ + +#endif /* GCC_GCOV_IO_H */ diff --git a/src/lib/gcov-iov.h b/src/lib/gcov-iov.h new file mode 100644 index 0000000..09951fb --- /dev/null +++ b/src/lib/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `4.7.2 (4 7) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3430372a) /* 407* */ diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 206e82b..eed243a 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -42,6 +42,7 @@ it with the version available from LANL. #if CONFIG_WRITE_HIGH_TABLES #include #endif +#include #include /** @@ -62,6 +63,10 @@ void hardwaremain(int boot_complete) timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); +#if CONFIG_COVERAGE + coverage_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); diff --git a/src/lib/libgcov.c b/src/lib/libgcov.c new file mode 100644 index 0000000..4adf75e --- /dev/null +++ b/src/lib/libgcov.c @@ -0,0 +1,1157 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define __COREBOOT__ +#ifdef __COREBOOT__ +#include +#include +#include +#include +typedef s32 pid_t; +#define gcc_assert(x) ASSERT(x) +#define fprintf(file, x...) printk(BIOS_ERR, x) +#define alloca(size) __builtin_alloca (size) +#include "gcov-glue.c" + +/* Define MACROs to be used by coreboot compilation. */ +# define L_gcov +# define L_gcov_interval_profiler +# define L_gcov_pow2_profiler +# define L_gcov_one_value_profiler +# define L_gcov_indirect_call_profiler +# define L_gcov_average_profiler +# define L_gcov_ior_profiler + +# define HAVE_CC_TLS 0 +# define __GCOV_KERNEL__ + +# define IN_LIBGCOV 1 +# define IN_GCOV 0 +#else /* __COREBOOT__ */ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#endif /* __COREBOOT__ */ + +#ifndef __COREBOOT__ +#if defined(inhibit_libc) +#define IN_LIBGCOV (-1) +#else +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include +#define IN_LIBGCOV 1 +#if defined(L_gcov) +#define GCOV_LINKAGE /* nothing */ +#endif +#endif +#endif /* __COREBOOT__ */ +#include "gcov-io.h" + +#if defined(inhibit_libc) +/* If libc and its header files are not available, provide dummy functions. */ + +#ifdef L_gcov +void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} +void __gcov_flush (void) {} +#endif + +#ifdef L_gcov_merge_add +void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_single +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#ifdef L_gcov_merge_delta +void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif + +#else + +#ifndef __COREBOOT__ +#include +#if GCOV_LOCKED +#include +#include +#include +#endif +#else +void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} +#endif /* __COREBOOT__ */ + +#ifdef L_gcov +#include "gcov-io.c" + +struct gcov_fn_buffer +{ + struct gcov_fn_buffer *next; + unsigned fn_ix; + struct gcov_fn_info info; + /* note gcov_fn_info ends in a trailing array. */ +}; + +/* Chain of per-object gcov structures. */ +static struct gcov_info *gcov_list; + +/* Size of the longest file name. */ +static size_t gcov_max_filename = 0; + +/* Make sure path component of the given FILENAME exists, create + missing directories. FILENAME must be writable. + Returns zero on success, or -1 if an error occurred. */ + +static int +create_file_directory (char *filename) +{ +#ifdef __COREBOOT__ + (void) filename; + return 0; +#else +#if !defined(TARGET_POSIX_IO) && !defined(_WIN32) + (void) filename; + return -1; +#else + char *s; + + s = filename; + + if (HAS_DRIVE_SPEC(s)) + s += 2; + if (IS_DIR_SEPARATOR(*s)) + ++s; + for (; *s != '\0'; s++) + if (IS_DIR_SEPARATOR(*s)) + { + char sep = *s; + *s = '\0'; + + /* Try to make directory if it doesn't already exist. */ + if (access (filename, F_OK) == -1 +#ifdef TARGET_POSIX_IO + && mkdir (filename, 0755) == -1 +#else + && mkdir (filename) == -1 +#endif + /* The directory might have been made by another process. */ + && errno != EEXIST) + { + fprintf (stderr, "profiling:%s:Cannot create directory\n", + filename); + *s = sep; + return -1; + }; + + *s = sep; + }; + return 0; +#endif +#endif +} + +static struct gcov_fn_buffer * +free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer, + unsigned limit) +{ + struct gcov_fn_buffer *next; + unsigned ix, n_ctr = 0; + + if (!buffer) + return 0; + next = buffer->next; + + for (ix = 0; ix != limit; ix++) + if (gi_ptr->merge[ix]) + free (buffer->info.ctrs[n_ctr++].values); + free (buffer); + return next; +} + +static struct gcov_fn_buffer ** +buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr, + struct gcov_fn_buffer **end_ptr, unsigned fn_ix) +{ + unsigned n_ctrs = 0, ix = 0; + struct gcov_fn_buffer *fn_buffer; + unsigned len; + + for (ix = GCOV_COUNTERS; ix--;) + if (gi_ptr->merge[ix]) + n_ctrs++; + + len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs; + fn_buffer = (struct gcov_fn_buffer *)malloc (len); + + if (!fn_buffer) + goto fail; + + fn_buffer->next = 0; + fn_buffer->fn_ix = fn_ix; + fn_buffer->info.ident = gcov_read_unsigned (); + fn_buffer->info.lineno_checksum = gcov_read_unsigned (); + fn_buffer->info.cfg_checksum = gcov_read_unsigned (); + + for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++) + { + gcov_unsigned_t length; + gcov_type *values; + + if (!gi_ptr->merge[ix]) + continue; + + if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix)) + { + len = 0; + goto fail; + } + + length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ()); + len = length * sizeof (gcov_type); + values = (gcov_type *)malloc (len); + if (!values) + goto fail; + + fn_buffer->info.ctrs[n_ctrs].num = length; + fn_buffer->info.ctrs[n_ctrs].values = values; + + while (length--) + *values++ = gcov_read_counter (); + n_ctrs++; + } + + *end_ptr = fn_buffer; + return &fn_buffer->next; + +fail: + fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix, + len ? "cannot allocate" : "counter mismatch", len ? len : ix); + + return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); +} + +/* Add an unsigned value to the current crc */ + +static gcov_unsigned_t +crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) +{ + unsigned ix; + + for (ix = 32; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; + crc32 <<= 1; + crc32 ^= feedback; + } + + return crc32; +} + +/* Check if VERSION of the info block PTR matches libgcov one. + Return 1 on success, or zero in case of versions mismatch. + If FILENAME is not NULL, its value used for reporting purposes + instead of value from the info block. */ + +static int +gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, + const char *filename) +{ + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fprintf (stderr, + "profiling:%s:Version mismatch - expected %.4s got %.4s\n", + filename? filename : ptr->filename, e, v); + return 0; + } + return 1; +} + +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. We use this + program's checksum to make sure we only accumulate whole program + statistics to the correct summary. An object file might be embedded + in two separate programs, and we must keep the two program + summaries separate. */ + +static void +gcov_exit (void) +{ + struct gcov_info *gi_ptr; + const struct gcov_fn_info *gfi_ptr; + struct gcov_summary this_prg; /* summary for program. */ + struct gcov_summary all_prg; /* summary for all instances of program. */ + struct gcov_ctr_summary *cs_ptr; + const struct gcov_ctr_info *ci_ptr; + unsigned t_ix; + int f_ix = 0; + gcov_unsigned_t c_num; + const char *gcov_prefix; + int gcov_prefix_strip = 0; + size_t prefix_length; + char *gi_filename, *gi_filename_up; + gcov_unsigned_t crc32 = 0; + + memset (&all_prg, 0, sizeof (all_prg)); + /* Find the totals for this execution. */ + memset (&this_prg, 0, sizeof (this_prg)); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); + crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); + + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (gfi_ptr && gfi_ptr->key != gi_ptr) + gfi_ptr = 0; + + crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); + crc32 = crc32_unsigned (crc32, + gfi_ptr ? gfi_ptr->lineno_checksum : 0); + if (!gfi_ptr) + continue; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + cs_ptr = &this_prg.ctrs[t_ix]; + cs_ptr->num += ci_ptr->num; + crc32 = crc32_unsigned (crc32, ci_ptr->num); + + for (c_num = 0; c_num < ci_ptr->num; c_num++) + { + cs_ptr->sum_all += ci_ptr->values[c_num]; + if (cs_ptr->run_max < ci_ptr->values[c_num]) + cs_ptr->run_max = ci_ptr->values[c_num]; + } + ci_ptr++; + } + } + } + +#ifndef __COREBOOT__ + { + /* Check if the level of dirs to strip off specified. */ + char *tmp = getenv("GCOV_PREFIX_STRIP"); + if (tmp) + { + gcov_prefix_strip = atoi (tmp); + /* Do not consider negative values. */ + if (gcov_prefix_strip < 0) + gcov_prefix_strip = 0; + } + } + + /* Get file name relocation prefix. Non-absolute values are ignored. */ + gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix) + { + prefix_length = strlen(gcov_prefix); + + /* Remove an unnecessary trailing '/' */ + if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; + } + else +#endif + prefix_length = 0; + + /* If no prefix was specified and a prefix stip, then we assume + relative. */ + if (gcov_prefix_strip != 0 && prefix_length == 0) + { + gcov_prefix = "."; + prefix_length = 1; + } + /* Allocate and initialize the filename scratch space plus one. */ + gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); + if (prefix_length) + memcpy (gi_filename, gcov_prefix, prefix_length); + gi_filename_up = gi_filename + prefix_length; + + /* Now merge each file. */ + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned n_counts; + struct gcov_summary prg; /* summary for this object over all + program. */ + struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all; + int error = 0; + gcov_unsigned_t tag, length; + gcov_position_t summary_pos = 0; + gcov_position_t eof_pos = 0; + const char *fname, *s; + struct gcov_fn_buffer *fn_buffer = 0; + struct gcov_fn_buffer **fn_tail = &fn_buffer; + + fname = gi_ptr->filename; + + /* Avoid to add multiple drive letters into combined path. */ + if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) + fname += 2; + + /* Build relocated filename, stripping off leading + directories from the initial filename if requested. */ + if (gcov_prefix_strip > 0) + { + int level = 0; + s = fname; + if (IS_DIR_SEPARATOR(*s)) + ++s; + + /* Skip selected directory levels. */ + for (; (*s != '\0') && (level < gcov_prefix_strip); s++) + if (IS_DIR_SEPARATOR(*s)) + { + fname = s; + level++; + } + } + + /* Update complete filename with stripped original. */ + if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + { + /* If prefix is given, add directory separator. */ + strcpy (gi_filename_up, "/"); + strcpy (gi_filename_up + 1, fname); + } + else + strcpy (gi_filename_up, fname); + + if (!gcov_open (gi_filename)) + { + /* Open failed likely due to missed directory. + Create directory and retry to open file. */ + if (create_file_directory (gi_filename)) + { + fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + continue; + } + if (!gcov_open (gi_filename)) + { + fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + continue; + } + } + + tag = gcov_read_unsigned (); + if (tag) + { + /* Merge data from file. */ + if (tag != GCOV_DATA_MAGIC) + { + fprintf (stderr, "profiling:%s:Not a gcov data file\n", + gi_filename); + goto read_fatal; + } + length = gcov_read_unsigned (); + if (!gcov_version (gi_ptr, length, gi_filename)) + goto read_fatal; + + length = gcov_read_unsigned (); + if (length != gi_ptr->stamp) + /* Read from a different compilation. Overwrite the file. */ + goto rewrite; + + /* Look for program summary. */ + for (f_ix = 0;;) + { + struct gcov_summary tmp; + + eof_pos = gcov_position (); + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_PROGRAM_SUMMARY) + break; + + f_ix--; + length = gcov_read_unsigned (); + if (length != GCOV_TAG_SUMMARY_LENGTH) + goto read_mismatch; + gcov_read_summary (&tmp); + if ((error = gcov_is_error ())) + goto read_error; + if (summary_pos || tmp.checksum != crc32) + goto next_summary; + + for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++) + if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num) + goto next_summary; + prg = tmp; + summary_pos = eof_pos; + + next_summary:; + } + + /* Merge execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; + f_ix++, tag = gcov_read_unsigned ()) + { + gfi_ptr = gi_ptr->functions[f_ix]; + + if (tag != GCOV_TAG_FUNCTION) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (!length) + /* This function did not appear in the other program. + We have nothing to merge. */ + continue; + + if (length != GCOV_TAG_FUNCTION_LENGTH) + goto read_mismatch; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + { + /* This function appears in the other program. We + need to buffer the information in order to write + it back out -- we'll be inserting data before + this point, so cannot simply keep the data in the + file. */ + fn_tail = buffer_fn_data (gi_filename, + gi_ptr, fn_tail, f_ix); + if (!fn_tail) + goto read_mismatch; + continue; + } + + length = gcov_read_unsigned (); + if (length != gfi_ptr->ident) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->lineno_checksum) + goto read_mismatch; + + length = gcov_read_unsigned (); + if (length != gfi_ptr->cfg_checksum) + goto read_mismatch; + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + gcov_merge_fn merge = gi_ptr->merge[t_ix]; + + if (!merge) + continue; + + tag = gcov_read_unsigned (); + length = gcov_read_unsigned (); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) + goto read_mismatch; + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } + if ((error = gcov_is_error ())) + goto read_error; + } + + if (tag) + { + read_mismatch:; + fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n", + gi_filename, f_ix >= 0 ? "function" : "summary", + f_ix < 0 ? -1 - f_ix : f_ix); + goto read_fatal; + } + } + goto rewrite; + + read_error:; + fprintf (stderr, "profiling:%s:%s merging\n", gi_filename, + error < 0 ? "Overflow": "Error"); + + goto read_fatal; + + rewrite:; + gcov_rewrite (); + if (!summary_pos) + { + memset (&prg, 0, sizeof (prg)); + summary_pos = eof_pos; + } + + /* Merge the summaries. */ + for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) + { + cs_prg = &prg.ctrs[t_ix]; + cs_tprg = &this_prg.ctrs[t_ix]; + cs_all = &all_prg.ctrs[t_ix]; + + if (gi_ptr->merge[t_ix]) + { + if (!cs_prg->runs++) + cs_prg->num = cs_tprg->num; + cs_prg->sum_all += cs_tprg->sum_all; + if (cs_prg->run_max < cs_tprg->run_max) + cs_prg->run_max = cs_tprg->run_max; + cs_prg->sum_max += cs_tprg->run_max; + } + else if (cs_prg->runs) + goto read_mismatch; + + if (!cs_all->runs && cs_prg->runs) + memcpy (cs_all, cs_prg, sizeof (*cs_all)); + else if (!all_prg.checksum + && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) + && memcmp (cs_all, cs_prg, sizeof (*cs_all))) + { + fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n", + gi_filename, GCOV_LOCKED + ? "" : " or concurrently updated without locking support"); + all_prg.checksum = ~0u; + } + } + + prg.checksum = crc32; + + /* Write out the data. */ + if (!eof_pos) + { + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); + } + + if (summary_pos) + gcov_seek (summary_pos); + + /* Generate whole program statistics. */ + gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg); + + if (summary_pos < eof_pos) + gcov_seek (eof_pos); + + /* Write execution counts for each function. */ + for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + unsigned buffered = 0; + + if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix) + { + /* Buffered data from another program. */ + buffered = 1; + gfi_ptr = &fn_buffer->info; + length = GCOV_TAG_FUNCTION_LENGTH; + } + else + { + gfi_ptr = gi_ptr->functions[f_ix]; + if (gfi_ptr && gfi_ptr->key == gi_ptr) + length = GCOV_TAG_FUNCTION_LENGTH; + else + length = 0; + } + + gcov_write_tag_length (GCOV_TAG_FUNCTION, length); + if (!length) + continue; + + gcov_write_unsigned (gfi_ptr->ident); + gcov_write_unsigned (gfi_ptr->lineno_checksum); + gcov_write_unsigned (gfi_ptr->cfg_checksum); + + ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + n_counts = ci_ptr->num; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + gcov_type *c_ptr = ci_ptr->values; + while (n_counts--) + gcov_write_counter (*c_ptr++); + ci_ptr++; + } + if (buffered) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + } + + gcov_write_unsigned (0); + + read_fatal:; + while (fn_buffer) + fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); + + if ((error = gcov_close ())) + fprintf (stderr, error < 0 ? + "profiling:%s:Overflow writing\n" : + "profiling:%s:Error writing\n", + gi_filename); + } +} + +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + +void +__gcov_init (struct gcov_info *info) +{ + if (!info->version || !info->n_functions) + return; + if (gcov_version (info, info->version, 0)) + { + size_t filename_length = strlen(info->filename); + + /* Refresh the longest file name information */ + if (filename_length > gcov_max_filename) + gcov_max_filename = filename_length; + +#ifndef __COREBOOT__ + if (!gcov_list) + atexit (gcov_exit); +#endif + + info->next = gcov_list; + gcov_list = info; + } + info->version = 0; +} + +/* Called before fork or exec - write out profile information gathered so + far and reset it to zero. This avoids duplication or loss of the + profile information gathered so far. */ + +void +__gcov_flush (void) +{ + const struct gcov_info *gi_ptr; + + gcov_exit (); + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + +#endif /* L_gcov */ + +#ifdef L_gcov_merge_add +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_add (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters += gcov_read_counter (); +} +#endif /* L_gcov_merge_add */ + +#ifdef L_gcov_merge_ior +/* The profile merging function that just adds the counters. It is given + an array COUNTERS of N_COUNTERS old counters and it reads the same number + of counters from the gcov file. */ +void +__gcov_merge_ior (gcov_type *counters, unsigned n_counters) +{ + for (; n_counters; counters++, n_counters--) + *counters |= gcov_read_counter (); +} +#endif + +#ifdef L_gcov_merge_single +/* The profile merging function for choosing the most common value. + It is given an array COUNTERS of N_COUNTERS old counters and it + reads the same number of counters from the gcov file. The counters + are split into 3-tuples where the members of the tuple have + meanings: + + -- the stored candidate on the most common value of the measured entity + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_single (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 3)); + n_measures = n_counters / 3; + for (i = 0; i < n_measures; i++, counters += 3) + { + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[0] == value) + counters[1] += counter; + else if (counter > counters[1]) + { + counters[0] = value; + counters[1] = counter - counters[1]; + } + else + counters[1] -= counter; + counters[2] += all; + } +} +#endif /* L_gcov_merge_single */ + +#ifdef L_gcov_merge_delta +/* The profile merging function for choosing the most common + difference between two consecutive evaluations of the value. It is + given an array COUNTERS of N_COUNTERS old counters and it reads the + same number of counters from the gcov file. The counters are split + into 4-tuples where the members of the tuple have meanings: + + -- the last value of the measured entity + -- the stored candidate on the most common difference + -- counter + -- total number of evaluations of the value */ +void +__gcov_merge_delta (gcov_type *counters, unsigned n_counters) +{ + unsigned i, n_measures; + gcov_type value, counter, all; + + gcc_assert (!(n_counters % 4)); + n_measures = n_counters / 4; + for (i = 0; i < n_measures; i++, counters += 4) + { + /* last = */ gcov_read_counter (); + value = gcov_read_counter (); + counter = gcov_read_counter (); + all = gcov_read_counter (); + + if (counters[1] == value) + counters[2] += counter; + else if (counter > counters[2]) + { + counters[1] = value; + counters[2] = counter - counters[2]; + } + else + counters[2] -= counter; + counters[3] += all; + } +} +#endif /* L_gcov_merge_delta */ + +#ifdef L_gcov_interval_profiler +/* If VALUE is in interval , then increases the + corresponding counter in COUNTERS. If the VALUE is above or below + the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased + instead. */ + +void +__gcov_interval_profiler (gcov_type *counters, gcov_type value, + int start, unsigned steps) +{ + gcov_type delta = value - start; + if (delta < 0) + counters[steps + 1]++; + else if (delta >= steps) + counters[steps]++; + else + counters[delta]++; +} +#endif + +#ifdef L_gcov_pow2_profiler +/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise + COUNTERS[0] is incremented. */ + +void +__gcov_pow2_profiler (gcov_type *counters, gcov_type value) +{ + if (value & (value - 1)) + counters[0]++; + else + counters[1]++; +} +#endif + +/* Tries to determine the most common value among its inputs. Checks if the + value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] + is incremented. If this is not the case and COUNTERS[1] is not zero, + COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and + VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this + function is called more than 50% of the time with one value, this value + will be in COUNTERS[0] in the end. + + In any case, COUNTERS[2] is incremented. */ + +static inline void +__gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) +{ + if (value == counters[0]) + counters[1]++; + else if (counters[1] == 0) + { + counters[1] = 1; + counters[0] = value; + } + else + counters[1]--; + counters[2]++; +} + +#ifdef L_gcov_one_value_profiler +void +__gcov_one_value_profiler (gcov_type *counters, gcov_type value) +{ + __gcov_one_value_profiler_body (counters, value); +} +#endif + +#ifdef L_gcov_indirect_call_profiler + +/* By default, the C++ compiler will use function addresses in the + vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero + tells the compiler to use function descriptors instead. The value + of this macro says how many words wide the descriptor is (normally 2), + but it may be dependent on target flags. Since we do not have access + to the target flags here we just check to see if it is set and use + that to set VTABLE_USES_DESCRIPTORS to 0 or 1. + + It is assumed that the address of a function descriptor may be treated + as a pointer to a function. */ + +#ifdef TARGET_VTABLE_USES_DESCRIPTORS +#define VTABLE_USES_DESCRIPTORS 1 +#else +#define VTABLE_USES_DESCRIPTORS 0 +#endif + +/* Tries to determine the most common value among its inputs. */ +void +__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, + void* cur_func, void* callee_func) +{ + /* If the C++ virtual tables contain function descriptors then one + function may have multiple descriptors and we need to dereference + the descriptors to see if they point to the same function. */ + if (cur_func == callee_func + || (VTABLE_USES_DESCRIPTORS && callee_func + && *(void **) cur_func == *(void **) callee_func)) + __gcov_one_value_profiler_body (counter, value); +} +#endif + + +#ifdef L_gcov_average_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_average_profiler (gcov_type *counters, gcov_type value) +{ + counters[0] += value; + counters[1] ++; +} +#endif + +#ifdef L_gcov_ior_profiler +/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want + to saturate up. */ + +void +__gcov_ior_profiler (gcov_type *counters, gcov_type value) +{ + *counters |= value; +} +#endif + +#ifdef L_gcov_fork +/* A wrapper for the fork function. Flushes the accumulated profiling data, so + that they are not counted twice. */ + +pid_t +__gcov_fork (void) +{ + __gcov_flush (); + return fork (); +} +#endif + +#ifdef L_gcov_execl +/* A wrapper for the execl function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execl (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execv (path, args); +} +#endif + +#ifdef L_gcov_execlp +/* A wrapper for the execlp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execlp (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + va_end (aq); + + return execvp (path, args); +} +#endif + +#ifdef L_gcov_execle +/* A wrapper for the execle function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execle (const char *path, char *arg, ...) +{ + va_list ap, aq; + unsigned i, length; + char **args; + char **envp; + + __gcov_flush (); + + va_start (ap, arg); + va_copy (aq, ap); + + length = 2; + while (va_arg (ap, char *)) + length++; + va_end (ap); + + args = (char **) alloca (length * sizeof (void *)); + args[0] = arg; + for (i = 1; i < length; i++) + args[i] = va_arg (aq, char *); + envp = va_arg (aq, char **); + va_end (aq); + + return execve (path, args, envp); +} +#endif + +#ifdef L_gcov_execv +/* A wrapper for the execv function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execv (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execv (path, argv); +} +#endif + +#ifdef L_gcov_execvp +/* A wrapper for the execvp function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execvp (const char *path, char *const argv[]) +{ + __gcov_flush (); + return execvp (path, argv); +} +#endif + +#ifdef L_gcov_execve +/* A wrapper for the execve function. Flushes the accumulated profiling data, so + that they are not lost. */ + +int +__gcov_execve (const char *path, char *const argv[], char *const envp[]) +{ + __gcov_flush (); + return execve (path, argv, envp); +} +#endif +#endif /* inhibit_libc */ diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 2556a14..c5fb62a 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -32,6 +32,7 @@ #if CONFIG_COLLECT_TIMESTAMPS #include #endif +#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR @@ -518,6 +519,9 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) #if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); #endif +#if CONFIG_COVERAGE + coverage_exit(); +#endif /* Before we go off to run the payload, see if * we stayed within our bounds. diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index a777a8f..bc6bd6b 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define MAP_BYTES (1024*1024) @@ -82,7 +84,7 @@ static void *map_memory(u64 physical) /* Mapped memory must be aligned to page size */ p = physical & ~(page - 1); - debug("Mapping 1MB of physical memory at %zx.\n", p); + debug("Mapping 1MB of physical memory at 0x%zx.\n", p); v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); @@ -103,8 +105,13 @@ static void *map_memory(u64 physical) static void unmap_memory(void) { + if (mapped_virtual == NULL) { + fprintf(stderr, "Error unmapping memory\n"); + return; + } debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); munmap(mapped_virtual, MAP_BYTES); + mapped_virtual = NULL; } /* @@ -347,7 +354,7 @@ struct cbmem_entry { uint64_t size; }; -void dump_cbmem_toc(void) +static void dump_cbmem_toc(void) { int i; uint64_t start; @@ -374,7 +381,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_GDT: printf("GDT "); break; case CBMEM_ID_ACPI: printf("ACPI "); break; case CBMEM_ID_ACPI_GNVS: printf("ACPI GNVS "); break; - case CBMEM_ID_CBTABLE: printf("COREBOOTE "); break; + case CBMEM_ID_CBTABLE: printf("COREBOOT "); break; case CBMEM_ID_PIRQ: printf("IRQ TABLE "); break; case CBMEM_ID_MPTABLE: printf("SMP TABLE "); break; case CBMEM_ID_RESUME: printf("ACPI RESUME "); break; @@ -384,6 +391,7 @@ void dump_cbmem_toc(void) case CBMEM_ID_MRCDATA: printf("MRC DATA "); break; case CBMEM_ID_CONSOLE: printf("CONSOLE "); break; case CBMEM_ID_ELOG: printf("ELOG "); break; + case CBMEM_ID_COVERAGE: printf("COVERAGE "); break; default: printf("%08x ", entries[i].id); break; } @@ -393,7 +401,111 @@ void dump_cbmem_toc(void) unmap_memory(); } -void print_version(void) +#define COVERAGE_MAGIC 0x584d4153 +struct file { + uint32_t magic; + uint32_t next; + uint32_t filename; + uint32_t data; + int offset; + int len; +}; + +static int mkpath(char *path, mode_t mode) +{ + assert (path && *path); + char *p; + for (p = strchr(path+1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) { + *p = '/'; + return -1; + } + } + *p = '/'; + } + return 0; +} + +static void dump_coverage(void) +{ + int i, found = 0; + uint64_t start; + struct cbmem_entry *entries; + void *coverage; + unsigned long phys_offset; +#define phys_to_virt(x) ((void *)(unsigned long)(x) + phys_offset) + + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot table area found!\n"); + return; + } + + start = unpack_lb64(cbmem.start); + + entries = (struct cbmem_entry *)map_memory(start); + + for (i=0; imagic == COVERAGE_MAGIC) { + FILE *f; + char *filename; + + debug(" -> %s\n", (char *)phys_to_virt(file->filename)); + filename = strdup((char *)phys_to_virt(file->filename)); + if (mkpath(filename, 0755) == -1) { + perror("Directory for coverage data could " + "not be created"); + exit(1); + } + f = fopen(filename, "wb"); + if (!f) { + printf("Could not open %s: %s\n", + filename, strerror(errno)); + exit(1); + } + if (fwrite((void *)phys_to_virt(file->data), + file->len, 1, f) != 1) { + printf("Could not write to %s: %s\n", + filename, strerror(errno)); + exit(1); + } + fclose(f); + free(filename); + + if (file->next) + file = (struct file *)phys_to_virt(file->next); + else + file = NULL; + } + unmap_memory(); +} + +static void print_version(void) { printf("cbmem v%s -- ", CBMEM_VERSION); printf("Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.\n\n"); @@ -409,11 +521,12 @@ void print_version(void) "along with this program. If not, see .\n\n"); } -void print_usage(const char *name) +static void print_usage(const char *name) { - printf("usage: %s [-vh?]\n", name); + printf("usage: %s [-cCltVvh?]\n", name); printf("\n" " -c | --console: print cbmem console\n" + " -C | --coverage: dump coverage information\n" " -l | --list: print cbmem table of contents\n" " -t | --timestamps: print timestamp information\n" " -V | --verbose: verbose (debugging) output\n" @@ -430,12 +543,14 @@ int main(int argc, char** argv) int print_defaults = 1; int print_console = 0; + int print_coverage = 0; int print_list = 0; int print_timestamps = 0; int opt, option_index = 0; static struct option long_options[] = { {"console", 0, 0, 'c'}, + {"coverage", 0, 0, 'C'}, {"list", 0, 0, 'l'}, {"timestamps", 0, 0, 't'}, {"verbose", 0, 0, 'V'}, @@ -443,13 +558,17 @@ int main(int argc, char** argv) {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cltVvh?", + while ((opt = getopt_long(argc, argv, "cCltVvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': print_console = 1; print_defaults = 0; break; + case 'C': + print_coverage = 1; + print_defaults = 0; + break; case 'l': print_list = 1; print_defaults = 0; @@ -490,6 +609,9 @@ int main(int argc, char** argv) if (print_console) dump_console(); + if (print_coverage) + dump_coverage(); + if (print_list) dump_cbmem_toc(); From gerrit at coreboot.org Thu Jan 10 01:29:37 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 01:29:37 +0100 Subject: [coreboot] New patch to review for coreboot: c46a92b armv7: delete some unused files References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2121 -gerrit commit c46a92bfab281bd8eb5c74acb53c1d5c104f7c36 Author: David Hendricks Date: Wed Jan 9 16:12:23 2013 -0800 armv7: delete some unused files Change-Id: I4601b97cbd7dbfb6ee742b3920d2aac4ac49b958 Signed-off-by: David Hendricks --- src/arch/armv7/start.S | 542 ----------------------------- src/cpu/samsung/exynos5250/lowlevel_init.S | 32 -- src/cpu/samsung/exynos5250/spl.c | 41 --- 3 files changed, 615 deletions(-) diff --git a/src/arch/armv7/start.S b/src/arch/armv7/start.S deleted file mode 100644 index 8af48eb..0000000 --- a/src/arch/armv7/start.S +++ /dev/null @@ -1,542 +0,0 @@ -/* - * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core - * - * Copyright (c) 2004 Texas Instruments - * - * Copyright (c) 2001 Marius Gr?ger - * Copyright (c) 2002 Alex Z?pke - * Copyright (c) 2002 Gary Jennejohn - * Copyright (c) 2003 Richard Woodruff - * Copyright (c) 2003 Kshitij - * Copyright (c) 2006-2008 Syed Mohammed Khasim - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -.globl _start -_start: b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq -#ifdef CONFIG_SPL_BUILD -_undefined_instruction: .word _undefined_instruction -_software_interrupt: .word _software_interrupt -_prefetch_abort: .word _prefetch_abort -_data_abort: .word _data_abort -_not_used: .word _not_used -_irq: .word _irq -_fiq: .word _fiq -_pad: .word 0x12345678 /* now 16*4=64 */ -#else -_undefined_instruction: .word undefined_instruction -_software_interrupt: .word software_interrupt -_prefetch_abort: .word prefetch_abort -_data_abort: .word data_abort -_not_used: .word not_used -_irq: .word irq -_fiq: .word fiq -_pad: .word 0x12345678 /* now 16*4=64 */ -#endif /* CONFIG_SPL_BUILD */ - -.global _end_vect -_end_vect: - - .balignl 16,0xdeadbeef -/************************************************************************* - * - * Startup Code (reset vector) - * - * do important init only if we don't start from memory! - * setup Memory and board specific bits prior to relocation. - * relocate armboot to ram - * setup stack - * - *************************************************************************/ - -.globl _TEXT_BASE -_TEXT_BASE: - .word CONFIG_SYS_TEXT_BASE - -/* - * These are defined in the board-specific linker script. - */ -.globl _bss_start_ofs -_bss_start_ofs: - .word _bss - _start - -.global _image_copy_end_ofs -_image_copy_end_ofs: - .word __image_copy_end - _start - -.globl _bss_end_ofs -_bss_end_ofs: - .word _ebss - _start -# .word __bss_end__ - _start - -.globl _end_ofs -_end_ofs: - .word _end - _start - -#ifdef CONFIG_USE_IRQ -/* IRQ stack memory (calculated at run-time) */ -.globl IRQ_STACK_START -IRQ_STACK_START: - .word 0x0badc0de - -/* IRQ stack memory (calculated at run-time) */ -.globl FIQ_STACK_START -FIQ_STACK_START: - .word 0x0badc0de -#endif - -/* IRQ stack memory (calculated at run-time) + 8 bytes */ -.globl IRQ_STACK_START_IN -IRQ_STACK_START_IN: - .word 0x0badc0de - -/* - * the actual reset code - */ - -reset: -/* bl save_boot_params */ - /* - * set the cpu to SVC32 mode - */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - msr cpsr,r0 - -#if !defined(CONFIG_TEGRA2) -/* - * Setup vector: - * (OMAP4 spl TEXT_BASE is not 32 byte aligned. - * Continue to use ROM code vector only in OMAP4 spl) - */ -#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) - /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ - mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register - bic r0, #CR_V @ V = 0 - mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register - - /* Set vector address in CP15 VBAR register */ - ldr r0, =_start - mcr p15, 0, r0, c12, c0, 0 @Set VBAR -#endif -#endif /* !Tegra2 */ - - /* the mask ROM code should have PLL and others stable */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT - /* - * FIXME(dhendrix): Do we need to explicitly disable icache/dcache - * first? See example 15-3 in Cortex-A programmers guide... - */ - bl cpu_init_cp15 - bl cpu_init_crit -#endif - -/* Set stackpointer in internal RAM to call board_init_f */ -call_board_init_f: - ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) - bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ - ldr r0,=0x00000000 - bl board_init_f - -/*------------------------------------------------------------------------------*/ - -/* - * void relocate_code (addr_sp, gd, addr_moni) - * - * This "function" does not return, instead it continues in RAM - * after relocating the monitor code. - * - */ - .globl relocate_code -relocate_code: - mov r4, r0 /* save addr_sp */ - mov r5, r1 /* save addr of gd */ - mov r6, r2 /* save addr of destination */ - - /* Set up the stack */ -stack_setup: - mov sp, r4 - - adr r0, _start - subs r9, r6, r0 /* r9 <- relocation offset */ - beq clear_bss /* skip relocation */ - mov r1, r6 /* r1 <- scratch for copy_loop */ - ldr r3, _image_copy_end_ofs - add r2, r0, r3 /* r2 <- source end address */ - -copy_loop: - ldmia r0!, {r9-r10} /* copy from source address [r0] */ - stmia r1!, {r9-r10} /* copy to target address [r1] */ - cmp r0, r2 /* until source end address [r2] */ - blo copy_loop - -#ifndef CONFIG_SPL_BUILD - /* - * fix .rel.dyn relocations - */ - ldr r0, _TEXT_BASE /* r0 <- Text base */ - sub r9, r6, r0 /* r9 <- relocation offset */ - ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ - add r10, r10, r0 /* r10 <- sym table in FLASH */ - ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ - add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ - ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ - add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ -fixloop: - ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ - add r0, r0, r9 /* r0 <- location to fix up in RAM */ - ldr r1, [r2, #4] - and r7, r1, #0xff - cmp r7, #23 /* relative fixup? */ - beq fixrel - cmp r7, #2 /* absolute fixup? */ - beq fixabs - /* ignore unknown type of fixup */ - b fixnext -fixabs: - /* absolute fix: set location to (offset) symbol value */ - mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ - add r1, r10, r1 /* r1 <- address of symbol in table */ - ldr r1, [r1, #4] /* r1 <- symbol value */ - add r1, r1, r9 /* r1 <- relocated sym addr */ - b fixnext -fixrel: - /* relative fix: increase location by offset */ - ldr r1, [r0] - add r1, r1, r9 -fixnext: - str r1, [r0] - add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ - cmp r2, r3 - blo fixloop - b clear_bss -_rel_dyn_start_ofs: - .word __rel_dyn_start - _start -_rel_dyn_end_ofs: - .word __rel_dyn_end - _start -_dynsym_start_ofs: - .word __dynsym_start - _start - -#endif /* #ifndef CONFIG_SPL_BUILD */ - -clear_bss: -#ifdef CONFIG_SPL_BUILD - /* No relocation for SPL */ - ldr r0, =_bss - ldr r1, =_ebss -#else - ldr r0, _bss_start_ofs - ldr r1, _bss_end_ofs - mov r4, r6 /* reloc addr */ - add r0, r0, r4 - add r1, r1, r4 -#endif - mov r2, #0x00000000 /* clear */ - -clbss_l:str r2, [r0] /* clear loop... */ - add r0, r0, #4 - cmp r0, r1 - bne clbss_l - -/* - * We are done. Do not return, instead branch to second part of board - * initialization, now running from RAM. - */ -jump_2_ram: -/* - * If I-cache is enabled invalidate it - */ -#ifndef CONFIG_SYS_ICACHE_OFF - mcr p15, 0, r0, c7, c5, 0 @ invalidate icache - mcr p15, 0, r0, c7, c10, 4 @ DSB - mcr p15, 0, r0, c7, c5, 4 @ ISB -#endif - ldr r0, _board_init_r_ofs - adr r1, _start - add lr, r0, r1 - add lr, lr, r9 - /* setup parameters for board_init_r */ - mov r0, r5 /* gd_t */ - mov r1, r6 /* dest_addr */ - /* jump to it ... */ - mov pc, lr - -_board_init_r_ofs: - .word board_init_r - _start - -/************************************************************************* - * - * cpu_init_cp15 - * - * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless - * CONFIG_SYS_ICACHE_OFF is defined. - * - *************************************************************************/ -.globl cpu_init_cp15 -cpu_init_cp15: - /* - * Invalidate L1 I/D - */ - mov r0, #0 @ set up for MCR - mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs - mcr p15, 0, r0, c7, c5, 0 @ invalidate icache - mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array - mcr p15, 0, r0, c7, c10, 4 @ DSB - mcr p15, 0, r0, c7, c5, 4 @ ISB - - /* - * disable MMU stuff and caches - */ - mrc p15, 0, r0, c1, c0, 0 - bic r0, r0, #0x00002000 @ clear bits 13 (--V-) - bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) - orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB -#ifdef CONFIG_SYS_ICACHE_OFF - bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache -#else - orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache -#endif - mcr p15, 0, r0, c1, c0, 0 - mov pc, lr @ back to my caller - - -#ifndef CONFIG_SKIP_LOWLEVEL_INIT -/************************************************************************* - * - * CPU_init_critical registers - * - * setup important registers - * setup memory timing - * - *************************************************************************/ -cpu_init_crit: - /* - * Jump to board specific initialization... - * The Mask ROM will have already initialized - * basic memory. Go here to bump up clock rate and handle - * wake up conditions. - */ - mov ip, lr @ persevere link reg across call - bl lowlevel_init @ go setup pll,mux,memory - mov lr, ip @ restore link - mov pc, lr @ back to my caller -#endif - -#ifndef CONFIG_SPL_BUILD -/* - ************************************************************************* - * - * Interrupt handling - * - ************************************************************************* - */ -@ -@ IRQ stack frame. -@ -#define S_FRAME_SIZE 72 - -#define S_OLD_R0 68 -#define S_PSR 64 -#define S_PC 60 -#define S_LR 56 -#define S_SP 52 - -#define S_IP 48 -#define S_FP 44 -#define S_R10 40 -#define S_R9 36 -#define S_R8 32 -#define S_R7 28 -#define S_R6 24 -#define S_R5 20 -#define S_R4 16 -#define S_R3 12 -#define S_R2 8 -#define S_R1 4 -#define S_R0 0 - -#define MODE_SVC 0x13 -#define I_BIT 0x80 - -/* - * use bad_save_user_regs for abort/prefetch/undef/swi ... - * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling - */ - - .macro bad_save_user_regs - sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current - @ user stack - stmia sp, {r0 - r12} @ Save user registers (now in - @ svc mode) r0-r12 - ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort - @ stack - ldmia r2, {r2 - r3} @ get values for "aborted" pc - @ and cpsr (into parm regs) - add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack - - add r5, sp, #S_SP - mov r1, lr - stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr - mov r0, sp @ save current stack into r0 - @ (param register) - .endm - - .macro irq_save_user_regs - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ Calling r0-r12 - add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! - @ a reserved stack spot would - @ be good. - stmdb r8, {sp, lr}^ @ Calling SP, LR - str lr, [r8, #0] @ Save calling PC - mrs r6, spsr - str r6, [r8, #4] @ Save CPSR - str r0, [r8, #8] @ Save OLD_R0 - mov r0, sp - .endm - - .macro irq_restore_user_regs - ldmia sp, {r0 - lr}^ @ Calling r0 - lr - mov r0, r0 - ldr lr, [sp, #S_PC] @ Get PC - add sp, sp, #S_FRAME_SIZE - subs pc, lr, #4 @ return & move spsr_svc into - @ cpsr - .endm - - .macro get_bad_stack - ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter - @ in banked mode) - - str lr, [r13] @ save caller lr in position 0 - @ of saved stack - mrs lr, spsr @ get the spsr - str lr, [r13, #4] @ save spsr in position 1 of - @ saved stack - - mov r13, #MODE_SVC @ prepare SVC-Mode - @ msr spsr_c, r13 - msr spsr, r13 @ switch modes, make sure - @ moves will execute - mov lr, pc @ capture return pc - movs pc, lr @ jump to next instruction & - @ switch modes. - .endm - - .macro get_bad_stack_swi - sub r13, r13, #4 @ space on current stack for - @ scratch reg. - str r0, [r13] @ save R0's value. - ldr r0, IRQ_STACK_START_IN @ get data regions start - @ spots for abort stack - str lr, [r0] @ save caller lr in position 0 - @ of saved stack - mrs r0, spsr @ get the spsr - str lr, [r0, #4] @ save spsr in position 1 of - @ saved stack - ldr r0, [r13] @ restore r0 - add r13, r13, #4 @ pop stack entry - .endm - - .macro get_irq_stack @ setup IRQ stack - ldr sp, IRQ_STACK_START - .endm - - .macro get_fiq_stack @ setup FIQ stack - ldr sp, FIQ_STACK_START - .endm - -/* - * exception handlers - */ - .align 5 -undefined_instruction: - get_bad_stack - bad_save_user_regs - bl do_undefined_instruction - - .align 5 -software_interrupt: - get_bad_stack_swi - bad_save_user_regs - bl do_software_interrupt - - .align 5 -prefetch_abort: - get_bad_stack - bad_save_user_regs - bl do_prefetch_abort - - .align 5 -data_abort: - get_bad_stack - bad_save_user_regs - bl do_data_abort - - .align 5 -not_used: - get_bad_stack - bad_save_user_regs - bl do_not_used - -#ifdef CONFIG_USE_IRQ - - .align 5 -irq: - get_irq_stack - irq_save_user_regs - bl do_irq - irq_restore_user_regs - - .align 5 -fiq: - get_fiq_stack - /* someone ought to write a more effective fiq_save_user_regs */ - irq_save_user_regs - bl do_fiq - irq_restore_user_regs - -#else - - .align 5 -irq: - get_bad_stack - bad_save_user_regs - bl do_irq - - .align 5 -fiq: - get_bad_stack - bad_save_user_regs - bl do_fiq - -#endif /* CONFIG_USE_IRQ */ -#endif /* CONFIG_SPL_BUILD */ diff --git a/src/cpu/samsung/exynos5250/lowlevel_init.S b/src/cpu/samsung/exynos5250/lowlevel_init.S deleted file mode 100644 index 883db9d..0000000 --- a/src/cpu/samsung/exynos5250/lowlevel_init.S +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Lowlevel setup for SMDK5250 board based on S5PC520 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - - .globl lowlevel_init -lowlevel_init: - /* - * Set the stack pointer, although it will be overwriten by the caller - * It seems we will not boot if this function is empty. - */ - ldr sp, =CONFIG_IRAM_STACK - mov pc, lr diff --git a/src/cpu/samsung/exynos5250/spl.c b/src/cpu/samsung/exynos5250/spl.c deleted file mode 100644 index 00b584a..0000000 --- a/src/cpu/samsung/exynos5250/spl.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* FIXME(dhendrix): file unneeded? */ -#if 0 -#include -#include -#include - -/* Get the u-boot size from the SPL parameter table */ -unsigned int exynos_get_uboot_size(void) -{ - struct spl_machine_param *param = spl_get_machine_params(); - - return param->uboot_size; -} - -/* Get the boot device from the SPL parameter table */ -enum boot_mode exynos_get_boot_device(void) -{ - struct spl_machine_param *param = spl_get_machine_params(); - - return param->boot_source; -} -#endif From gerrit at coreboot.org Thu Jan 10 01:29:38 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 01:29:38 +0100 Subject: [coreboot] New patch to review for coreboot: 546a0d2 armv7: update board_init_f function signature References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2122 -gerrit commit 546a0d290eafe438b50d30bca0bc98b321b35580 Author: David Hendricks Date: Wed Jan 9 16:14:00 2013 -0800 armv7: update board_init_f function signature We don't pass arguments when we jump out of assembly code. Change-Id: Iccf3a6f713e260b08f9ff47e8b542b9e96369166 Signed-off-by: David Hendricks --- src/arch/armv7/include/common.h | 3 ++- src/cpu/samsung/exynos5-common/spl_boot.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/arch/armv7/include/common.h b/src/arch/armv7/include/common.h index e21cfb0..6a590d6 100644 --- a/src/arch/armv7/include/common.h +++ b/src/arch/armv7/include/common.h @@ -164,7 +164,8 @@ void init_cmd_timeout(void); void reset_cmd_timeout(void); /* arch/$(ARCH)/lib/board.c */ -void board_init_f (ulong); +void board_init_f (void); +//void board_init_f (ulong); //void board_init_f (ulong) __attribute__ ((noreturn)); void board_init_r (gd_t *, ulong) __attribute__ ((noreturn)); int checkboard (void); diff --git a/src/cpu/samsung/exynos5-common/spl_boot.c b/src/cpu/samsung/exynos5-common/spl_boot.c index a734d5c..9b9bc23 100644 --- a/src/cpu/samsung/exynos5-common/spl_boot.c +++ b/src/cpu/samsung/exynos5-common/spl_boot.c @@ -308,7 +308,8 @@ static int __def_board_wakeup_permitted(void) int board_wakeup_permitted(void) __attribute__((weak, alias("__def_board_wakeup_permitted"))); -void board_init_f(unsigned long bootflag) +//void board_init_f(unsigned long bootflag) +void board_init_f(void) { /* * The gd struct is only needed for serial initialization. Since this From gerrit at coreboot.org Thu Jan 10 01:29:38 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 01:29:38 +0100 Subject: [coreboot] New patch to review for coreboot: 71dc405 snow: add max77686 driver in romstage and ramstage References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2123 -gerrit commit 71dc4051eeafe841703ecadfbe29e982a649b414 Author: David Hendricks Date: Wed Jan 9 16:22:12 2013 -0800 snow: add max77686 driver in romstage and ramstage Change-Id: Id3e20b1ab5d85cfd22e2dae2750f32007b7f8f74 Signed-off-by: David Hendricks --- src/drivers/maxim/max77686/Makefile.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/maxim/max77686/Makefile.inc b/src/drivers/maxim/max77686/Makefile.inc index b67595f..a5d7b90 100644 --- a/src/drivers/maxim/max77686/Makefile.inc +++ b/src/drivers/maxim/max77686/Makefile.inc @@ -17,4 +17,5 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -ramstage-$(CONFIG_DRIVER_MAXIM_77686) += max77686.c +romstage-$(CONFIG_DRIVER_MAXIM_MAX77686) += max77686.c +ramstage-$(CONFIG_DRIVER_MAXIM_MAX77686) += max77686.c From gerrit at coreboot.org Thu Jan 10 01:29:39 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 01:29:39 +0100 Subject: [coreboot] New patch to review for coreboot: eaffaa6 size optimizations for max77686 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2124 -gerrit commit eaffaa6cda62b9b03f4ac5f4a2b4e2998dacec2f Author: David Hendricks Date: Wed Jan 9 16:26:26 2013 -0800 size optimizations for max77686 This contains some size optimizations for the Maxim MAX77686 driver: - change max77686_para.vol_{min,div} from u32 to u16 (currently their max value is 50000 so it should be fine) - remove max77686_para.regnum which takes 4 bytes for each and is not used (Patch was originally written by Hung-Te Lin, I'm just uploading it) Change-Id: I24044427c49467e99380d1f60ebc59e69c285b22 Signed-off-by: Hung-Te Lin Signed-off-by: David Hendricks --- src/drivers/maxim/max77686/max77686.c | 88 ++++++++++++++++++----------------- src/drivers/maxim/max77686/max77686.h | 5 +- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/drivers/maxim/max77686/max77686.c b/src/drivers/maxim/max77686/max77686.c index 8fbcb8f..16fa7f5 100644 --- a/src/drivers/maxim/max77686/max77686.c +++ b/src/drivers/maxim/max77686/max77686.c @@ -21,9 +21,12 @@ * MA 02111-1307 USA */ +#include #include -#include -#include +//#include +#include + +#include "max77686.h" /* Chip register numbers (not exported from this module) */ enum { @@ -39,45 +42,45 @@ enum { * Max77686 parameters values * see max77686.h for parameters details */ -struct max77686_para max77686_param[] = {/*{regnum, vol_addr, vol_bitpos, +struct max77686_para max77686_param[] = {/*{vol_addr, vol_bitpos, vol_bitmask, reg_enaddr, reg_enbitpos, reg_enbitmask, reg_enbiton, reg_enbitoff, vol_min, vol_div}*/ - {PMIC_BUCK1, 0x11, 0x0, 0x3F, 0x10, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK2, 0x14, 0x0, 0xFF, 0x12, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK3, 0x1E, 0x0, 0xFF, 0x1C, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK4, 0x28, 0x0, 0xFF, 0x26, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK5, 0x31, 0x0, 0x3F, 0x30, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK6, 0x33, 0x0, 0x3F, 0x32, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK7, 0x35, 0x0, 0x3F, 0x34, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK8, 0x37, 0x0, 0x3F, 0x36, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK9, 0x39, 0x0, 0x3F, 0x38, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_LDO1, 0x40, 0x0, 0x3F, 0x40, 0x6, 0x3, 0x3, 0x0, 800, 25000}, - {PMIC_LDO2, 0x41, 0x0, 0x3F, 0x41, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO3, 0x42, 0x0, 0x3F, 0x42, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO4, 0x43, 0x0, 0x3F, 0x43, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO5, 0x44, 0x0, 0x3F, 0x44, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO6, 0x45, 0x0, 0x3F, 0x45, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO7, 0x46, 0x0, 0x3F, 0x46, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO8, 0x47, 0x0, 0x3F, 0x47, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO9, 0x48, 0x0, 0x3F, 0x48, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO10, 0x49, 0x0, 0x3F, 0x49, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO11, 0x4A, 0x0, 0x3F, 0x4A, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO12, 0x4B, 0x0, 0x3F, 0x4B, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO13, 0x4C, 0x0, 0x3F, 0x4C, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO14, 0x4D, 0x0, 0x3F, 0x4D, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO15, 0x4E, 0x0, 0x3F, 0x4E, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO16, 0x4F, 0x0, 0x3F, 0x4F, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO17, 0x50, 0x0, 0x3F, 0x50, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO18, 0x51, 0x0, 0x3F, 0x51, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO19, 0x52, 0x0, 0x3F, 0x52, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO20, 0x53, 0x0, 0x3F, 0x53, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO21, 0x54, 0x0, 0x3F, 0x54, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO22, 0x55, 0x0, 0x3F, 0x55, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO23, 0x56, 0x0, 0x3F, 0x56, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO24, 0x57, 0x0, 0x3F, 0x57, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO25, 0x58, 0x0, 0x3F, 0x58, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO26, 0x59, 0x0, 0x3F, 0x59, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_EN32KHZ_CP, 0x0, 0x0, 0x0, 0x7F, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0}, + {/* PMIC_BUCK1 */ 0x11, 0x0, 0x3F, 0x10, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK2 */ 0x14, 0x0, 0xFF, 0x12, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK3 */ 0x1E, 0x0, 0xFF, 0x1C, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK4 */ 0x28, 0x0, 0xFF, 0x26, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK5 */ 0x31, 0x0, 0x3F, 0x30, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK6 */ 0x33, 0x0, 0x3F, 0x32, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK7 */ 0x35, 0x0, 0x3F, 0x34, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK8 */ 0x37, 0x0, 0x3F, 0x36, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK9 */ 0x39, 0x0, 0x3F, 0x38, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_LDO1 */ 0x40, 0x0, 0x3F, 0x40, 0x6, 0x3, 0x3, 0x0, 800, 25000}, + {/* PMIC_LDO2 */ 0x41, 0x0, 0x3F, 0x41, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO3 */ 0x42, 0x0, 0x3F, 0x42, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO4 */ 0x43, 0x0, 0x3F, 0x43, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO5 */ 0x44, 0x0, 0x3F, 0x44, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO6 */ 0x45, 0x0, 0x3F, 0x45, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO7 */ 0x46, 0x0, 0x3F, 0x46, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO8 */ 0x47, 0x0, 0x3F, 0x47, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO9 */ 0x48, 0x0, 0x3F, 0x48, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO10 */ 0x49, 0x0, 0x3F, 0x49, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO11 */ 0x4A, 0x0, 0x3F, 0x4A, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO12 */ 0x4B, 0x0, 0x3F, 0x4B, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO13 */ 0x4C, 0x0, 0x3F, 0x4C, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO14 */ 0x4D, 0x0, 0x3F, 0x4D, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO15 */ 0x4E, 0x0, 0x3F, 0x4E, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO16 */ 0x4F, 0x0, 0x3F, 0x4F, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO17 */ 0x50, 0x0, 0x3F, 0x50, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO18 */ 0x51, 0x0, 0x3F, 0x51, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO19 */ 0x52, 0x0, 0x3F, 0x52, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO20 */ 0x53, 0x0, 0x3F, 0x53, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO21 */ 0x54, 0x0, 0x3F, 0x54, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO22 */ 0x55, 0x0, 0x3F, 0x55, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO23 */ 0x56, 0x0, 0x3F, 0x56, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO24 */ 0x57, 0x0, 0x3F, 0x57, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO25 */ 0x58, 0x0, 0x3F, 0x58, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO26 */ 0x59, 0x0, 0x3F, 0x59, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_EN32KHZ_CP */ 0x0, 0x0, 0x0, 0x7F, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0}, }; /* @@ -174,15 +177,15 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, } if (volt_units == MAX77686_UV) - vol_level = volt - pmic->vol_min * 1000; + vol_level = volt - (u32)pmic->vol_min * 1000; else - vol_level = (volt - pmic->vol_min) * 1000; + vol_level = (volt - (u32)pmic->vol_min) * 1000; if (vol_level < 0) { debug("Not a valid voltage level to set\n"); return -1; } - vol_level /= pmic->vol_div; + vol_level /= (u32)pmic->vol_div; clrsetbits_8(&read_data, pmic->vol_bitmask << pmic->vol_bitpos, vol_level << pmic->vol_bitpos); @@ -198,7 +201,6 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, debug("Failed to enable buck/ldo.\n"); return -1; } - return 0; } diff --git a/src/drivers/maxim/max77686/max77686.h b/src/drivers/maxim/max77686/max77686.h index 345471e..ee53e27 100644 --- a/src/drivers/maxim/max77686/max77686.h +++ b/src/drivers/maxim/max77686/max77686.h @@ -77,7 +77,6 @@ enum max77686_regnum { * @param vol_div voltage division value of given buck/ldo */ struct max77686_para { - enum max77686_regnum regnum; u8 vol_addr; u8 vol_bitpos; u8 vol_bitmask; @@ -86,8 +85,8 @@ struct max77686_para { u8 reg_enbitmask; u8 reg_enbiton; u8 reg_enbitoff; - u32 vol_min; - u32 vol_div; + u16 vol_min; + u16 vol_div; }; /* I2C device address for pmic max77686 */ From svetoslav.trochev at gmail.com Wed Jan 9 22:48:25 2013 From: svetoslav.trochev at gmail.com (Svetoslav Trochev) Date: Wed, 9 Jan 2013 13:48:25 -0800 Subject: [coreboot] Permanent solution of the UEFI Secure Boot problem?! Message-ID: Hi Everyone and Happy New Year. This summer I'm planning to buy new laptop. Also ongoing debates related to UEFI transition and current implementation of 'Secure Boot' requirement imposed by Microsoft's Windows 8 certification got me thinking and I would like to share my idea and see how many people have similar thoughts. Basically boils down to create Coreboot Reference Hardware for development, testing and daily use of coreboot. Here is my plan (warning it is not very well thought through): 1. See how many people are ready to buy new hardware and are interested to work on coreboot advancement. 2. If we have something like 10 people we can work together to define the spec sheet of 'perfect' laptop. 3. Once we have the spec sheet it should be very easy to find OEM and place one single order. In my experience 10 people buying same laptop will have zero impact, but 1 person buying 10 laptops gets notice right away, especially if the order is placed with small OEM. I suspect it will take some time and we might go over several upgrade cycles before we get where I would like, but if we make steady progress and get more people on-board we can get to the point where we can order custom systems that are build to our spec and get cooperation from interested commercial entities. 4. Once we have our identical hardware in hands of different developer we can employ divide and concur strategy in order to overcome any problems we will encounter making coreboot better then original UEFI/BIOS. 5. I was thinking to do this with laptop, but I do realize that could be more easy done using desktop motherboard. So, if we agree on the plan of action we can buy mainboards instead of laptops. 6. I also recognize that big group of coreboot developers are located in EU, so we might have to place two separate orders: one in USA and other in EU because we don't want to deal with import/export problems. We are going to have enough problems porting coreboot to new laptop. What do you guys think? Am I completely crazy to believe that we can make material change in our industry? -------------- next part -------------- An HTML attachment was scrubbed... URL: From gerrit at coreboot.org Thu Jan 10 02:04:18 2013 From: gerrit at coreboot.org (gerrit at coreboot.org) Date: Thu, 10 Jan 2013 02:04:18 +0100 Subject: [coreboot] Patch merged into coreboot/master: 92dd172 Fix 2 infinite loops if IMC doesn't respond References: Message-ID: the following patch was just integrated into master: commit 92dd172a573a7eff4774030fdfe5eb9625d59aa0 Author: Martin Roth Date: Tue Jan 8 13:36:14 2013 -0700 Fix 2 infinite loops if IMC doesn't respond ACPI code: The ACPI code is not currently being compiled in by default, but assuming that it will be at some point, I'm fixing the loop that waits for the IMC to respond after sending it a command. The loop now exits after 500ms, similar to the function in agesa. Agesa Code: a 16 bit variable will always be less than 100000. Change to be a 32 bit variable. Change-Id: I9430ef900a22d056871b744f3b1511abdfea516e Signed-off-by: Martin Roth Reviewed-on: http://review.coreboot.org/2119 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi Reviewed-by: Stefan Reinauer Reviewed-By: Patrick Georgi at Wed Jan 9 20:55:23 2013, giving +2 Build-Tested: build bot (Jenkins) at Wed Jan 9 19:27:00 2013, giving +1 Reviewed-By: Stefan Reinauer at Thu Jan 10 02:04:17 2013, giving +2 See http://review.coreboot.org/2119 for details. -gerrit From peter at stuge.se Thu Jan 10 02:23:30 2013 From: peter at stuge.se (Peter Stuge) Date: Thu, 10 Jan 2013 02:23:30 +0100 Subject: [coreboot] Permanent solution of the UEFI Secure Boot problem?! In-Reply-To: References: Message-ID: <20130110012330.29284.qmail@stuge.se> Svetoslav Trochev wrote: > In my experience 10 people buying same laptop will have zero > impact, but 1 person buying 10 laptops gets notice right away, > especially if the order is placed with small OEM. .. > What do you guys think? I think your numbers are off by four or five orders of magnitude. //Peter From gerrit at coreboot.org Thu Jan 10 02:32:02 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 02:32:02 +0100 Subject: [coreboot] Patch set updated for coreboot: e6bb1bd size optimizations for max77686 References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2124 -gerrit commit e6bb1bd568d231169d83a557028f25671b40be2c Author: David Hendricks Date: Wed Jan 9 16:26:26 2013 -0800 size optimizations for max77686 This contains some size optimizations for the Maxim MAX77686 driver: - change max77686_para.vol_{min,div} from u32 to u16 (currently their max value is 50000 so it should be fine) - remove max77686_para.regnum which takes 4 bytes for each and is not used (Patch was originally written by Hung-Te Lin, I'm just uploading it) Change-Id: I24044427c49467e99380d1f60ebc59e69c285b22 Signed-off-by: Hung-Te Lin Signed-off-by: David Hendricks --- src/drivers/maxim/max77686/max77686.c | 88 ++++++++++++++++++----------------- src/drivers/maxim/max77686/max77686.h | 5 +- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/drivers/maxim/max77686/max77686.c b/src/drivers/maxim/max77686/max77686.c index 8fbcb8f..16fa7f5 100644 --- a/src/drivers/maxim/max77686/max77686.c +++ b/src/drivers/maxim/max77686/max77686.c @@ -21,9 +21,12 @@ * MA 02111-1307 USA */ +#include #include -#include -#include +//#include +#include + +#include "max77686.h" /* Chip register numbers (not exported from this module) */ enum { @@ -39,45 +42,45 @@ enum { * Max77686 parameters values * see max77686.h for parameters details */ -struct max77686_para max77686_param[] = {/*{regnum, vol_addr, vol_bitpos, +struct max77686_para max77686_param[] = {/*{vol_addr, vol_bitpos, vol_bitmask, reg_enaddr, reg_enbitpos, reg_enbitmask, reg_enbiton, reg_enbitoff, vol_min, vol_div}*/ - {PMIC_BUCK1, 0x11, 0x0, 0x3F, 0x10, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK2, 0x14, 0x0, 0xFF, 0x12, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK3, 0x1E, 0x0, 0xFF, 0x1C, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK4, 0x28, 0x0, 0xFF, 0x26, 0x4, 0x3, 0x1, 0x0, 600, 12500}, - {PMIC_BUCK5, 0x31, 0x0, 0x3F, 0x30, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK6, 0x33, 0x0, 0x3F, 0x32, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK7, 0x35, 0x0, 0x3F, 0x34, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK8, 0x37, 0x0, 0x3F, 0x36, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_BUCK9, 0x39, 0x0, 0x3F, 0x38, 0x0, 0x3, 0x3, 0x0, 750, 50000}, - {PMIC_LDO1, 0x40, 0x0, 0x3F, 0x40, 0x6, 0x3, 0x3, 0x0, 800, 25000}, - {PMIC_LDO2, 0x41, 0x0, 0x3F, 0x41, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO3, 0x42, 0x0, 0x3F, 0x42, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO4, 0x43, 0x0, 0x3F, 0x43, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO5, 0x44, 0x0, 0x3F, 0x44, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO6, 0x45, 0x0, 0x3F, 0x45, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO7, 0x46, 0x0, 0x3F, 0x46, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO8, 0x47, 0x0, 0x3F, 0x47, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO9, 0x48, 0x0, 0x3F, 0x48, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO10, 0x49, 0x0, 0x3F, 0x49, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO11, 0x4A, 0x0, 0x3F, 0x4A, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO12, 0x4B, 0x0, 0x3F, 0x4B, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO13, 0x4C, 0x0, 0x3F, 0x4C, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO14, 0x4D, 0x0, 0x3F, 0x4D, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO15, 0x4E, 0x0, 0x3F, 0x4E, 0x6, 0x3, 0x1, 0x0, 800, 25000}, - {PMIC_LDO16, 0x4F, 0x0, 0x3F, 0x4F, 0x6, 0x3, 0x1, 0x0, 800, 50000}, - {PMIC_LDO17, 0x50, 0x0, 0x3F, 0x50, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO18, 0x51, 0x0, 0x3F, 0x51, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO19, 0x52, 0x0, 0x3F, 0x52, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO20, 0x53, 0x0, 0x3F, 0x53, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO21, 0x54, 0x0, 0x3F, 0x54, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO22, 0x55, 0x0, 0x3F, 0x55, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO23, 0x56, 0x0, 0x3F, 0x56, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO24, 0x57, 0x0, 0x3F, 0x57, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO25, 0x58, 0x0, 0x3F, 0x58, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_LDO26, 0x59, 0x0, 0x3F, 0x59, 0x6, 0x3, 0x3, 0x0, 800, 50000}, - {PMIC_EN32KHZ_CP, 0x0, 0x0, 0x0, 0x7F, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0}, + {/* PMIC_BUCK1 */ 0x11, 0x0, 0x3F, 0x10, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK2 */ 0x14, 0x0, 0xFF, 0x12, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK3 */ 0x1E, 0x0, 0xFF, 0x1C, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK4 */ 0x28, 0x0, 0xFF, 0x26, 0x4, 0x3, 0x1, 0x0, 600, 12500}, + {/* PMIC_BUCK5 */ 0x31, 0x0, 0x3F, 0x30, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK6 */ 0x33, 0x0, 0x3F, 0x32, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK7 */ 0x35, 0x0, 0x3F, 0x34, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK8 */ 0x37, 0x0, 0x3F, 0x36, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_BUCK9 */ 0x39, 0x0, 0x3F, 0x38, 0x0, 0x3, 0x3, 0x0, 750, 50000}, + {/* PMIC_LDO1 */ 0x40, 0x0, 0x3F, 0x40, 0x6, 0x3, 0x3, 0x0, 800, 25000}, + {/* PMIC_LDO2 */ 0x41, 0x0, 0x3F, 0x41, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO3 */ 0x42, 0x0, 0x3F, 0x42, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO4 */ 0x43, 0x0, 0x3F, 0x43, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO5 */ 0x44, 0x0, 0x3F, 0x44, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO6 */ 0x45, 0x0, 0x3F, 0x45, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO7 */ 0x46, 0x0, 0x3F, 0x46, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO8 */ 0x47, 0x0, 0x3F, 0x47, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO9 */ 0x48, 0x0, 0x3F, 0x48, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO10 */ 0x49, 0x0, 0x3F, 0x49, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO11 */ 0x4A, 0x0, 0x3F, 0x4A, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO12 */ 0x4B, 0x0, 0x3F, 0x4B, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO13 */ 0x4C, 0x0, 0x3F, 0x4C, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO14 */ 0x4D, 0x0, 0x3F, 0x4D, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO15 */ 0x4E, 0x0, 0x3F, 0x4E, 0x6, 0x3, 0x1, 0x0, 800, 25000}, + {/* PMIC_LDO16 */ 0x4F, 0x0, 0x3F, 0x4F, 0x6, 0x3, 0x1, 0x0, 800, 50000}, + {/* PMIC_LDO17 */ 0x50, 0x0, 0x3F, 0x50, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO18 */ 0x51, 0x0, 0x3F, 0x51, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO19 */ 0x52, 0x0, 0x3F, 0x52, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO20 */ 0x53, 0x0, 0x3F, 0x53, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO21 */ 0x54, 0x0, 0x3F, 0x54, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO22 */ 0x55, 0x0, 0x3F, 0x55, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO23 */ 0x56, 0x0, 0x3F, 0x56, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO24 */ 0x57, 0x0, 0x3F, 0x57, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO25 */ 0x58, 0x0, 0x3F, 0x58, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_LDO26 */ 0x59, 0x0, 0x3F, 0x59, 0x6, 0x3, 0x3, 0x0, 800, 50000}, + {/* PMIC_EN32KHZ_CP */ 0x0, 0x0, 0x0, 0x7F, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0}, }; /* @@ -174,15 +177,15 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, } if (volt_units == MAX77686_UV) - vol_level = volt - pmic->vol_min * 1000; + vol_level = volt - (u32)pmic->vol_min * 1000; else - vol_level = (volt - pmic->vol_min) * 1000; + vol_level = (volt - (u32)pmic->vol_min) * 1000; if (vol_level < 0) { debug("Not a valid voltage level to set\n"); return -1; } - vol_level /= pmic->vol_div; + vol_level /= (u32)pmic->vol_div; clrsetbits_8(&read_data, pmic->vol_bitmask << pmic->vol_bitpos, vol_level << pmic->vol_bitpos); @@ -198,7 +201,6 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, debug("Failed to enable buck/ldo.\n"); return -1; } - return 0; } diff --git a/src/drivers/maxim/max77686/max77686.h b/src/drivers/maxim/max77686/max77686.h index 345471e..ee53e27 100644 --- a/src/drivers/maxim/max77686/max77686.h +++ b/src/drivers/maxim/max77686/max77686.h @@ -77,7 +77,6 @@ enum max77686_regnum { * @param vol_div voltage division value of given buck/ldo */ struct max77686_para { - enum max77686_regnum regnum; u8 vol_addr; u8 vol_bitpos; u8 vol_bitmask; @@ -86,8 +85,8 @@ struct max77686_para { u8 reg_enbitmask; u8 reg_enbiton; u8 reg_enbitoff; - u32 vol_min; - u32 vol_div; + u16 vol_min; + u16 vol_div; }; /* I2C device address for pmic max77686 */ From gerrit at coreboot.org Thu Jan 10 02:32:04 2013 From: gerrit at coreboot.org (David Hendricks (dhendrix@chromium.org)) Date: Thu, 10 Jan 2013 02:32:04 +0100 Subject: [coreboot] Patch set updated for coreboot: f4e4909 armv7: delete some unused files References: Message-ID: David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2121 -gerrit commit f4e4909dcc258a3c0799bc1b8cad8601c202291d Author: David Hendricks Date: Wed Jan 9 16:12:23 2013 -0800 armv7: delete some unused files Change-Id: I4601b97cbd7dbfb6ee742b3920d2aac4ac49b958 Signed-off-by: David Hendricks --- src/arch/armv7/start.S | 542 ----------------------------- src/cpu/samsung/exynos5250/Makefile.inc | 2 - src/cpu/samsung/exynos5250/lowlevel_init.S | 32 -- src/cpu/samsung/exynos5250/spl.c | 41 --- 4 files changed, 617 deletions(-) diff --git a/src/arch/armv7/start.S b/src/arch/armv7/start.S deleted file mode 100644 index 8af48eb..0000000 --- a/src/arch/armv7/start.S +++ /dev/null @@ -1,542 +0,0 @@ -/* - * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core - * - * Copyright (c) 2004 Texas Instruments - * - * Copyright (c) 2001 Marius Gr?ger - * Copyright (c) 2002 Alex Z?pke - * Copyright (c) 2002 Gary Jennejohn - * Copyright (c) 2003 Richard Woodruff - * Copyright (c) 2003 Kshitij - * Copyright (c) 2006-2008 Syed Mohammed Khasim - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -.globl _start -_start: b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq -#ifdef CONFIG_SPL_BUILD -_undefined_instruction: .word _undefined_instruction -_software_interrupt: .word _software_interrupt -_prefetch_abort: .word _prefetch_abort -_data_abort: .word _data_abort -_not_used: .word _not_used -_irq: .word _irq -_fiq: .word _fiq -_pad: .word 0x12345678 /* now 16*4=64 */ -#else -_undefined_instruction: .word undefined_instruction -_software_interrupt: .word software_interrupt -_prefetch_abort: .word prefetch_abort -_data_abort: .word data_abort -_not_used: .word not_used -_irq: .word irq -_fiq: .word fiq -_pad: .word 0x12345678 /* now 16*4=64 */ -#endif /* CONFIG_SPL_BUILD */ - -.global _end_vect -_end_vect: - - .balignl 16,0xdeadbeef -/************************************************************************* - * - * Startup Code (reset vector) - * - * do important init only if we don't start from memory! - * setup Memory and board specific bits prior to relocation. - * relocate armboot to ram - * setup stack - * - *************************************************************************/ - -.globl _TEXT_BASE -_TEXT_BASE: - .word CONFIG_SYS_TEXT_BASE - -/* - * These are defined in the board-specific linker script. - */ -.globl _bss_start_ofs -_bss_start_ofs: - .word _bss - _start - -.global _image_copy_end_ofs -_image_copy_end_ofs: - .word __image_copy_end - _start - -.globl _bss_end_ofs -_bss_end_ofs: - .word _ebss - _start -# .word __bss_end__ - _start - -.globl _end_ofs -_end_ofs: - .word _end - _start - -#ifdef CONFIG_USE_IRQ -/* IRQ stack memory (calculated at run-time) */ -.globl IRQ_STACK_START -IRQ_STACK_START: - .word 0x0badc0de - -/* IRQ stack memory (calculated at run-time) */ -.globl FIQ_STACK_START -FIQ_STACK_START: - .word 0x0badc0de -#endif - -/* IRQ stack memory (calculated at run-time) + 8 bytes */ -.globl IRQ_STACK_START_IN -IRQ_STACK_START_IN: - .word 0x0badc0de - -/* - * the actual reset code - */ - -reset: -/* bl save_boot_params */ - /* - * set the cpu to SVC32 mode - */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - msr cpsr,r0 - -#if !defined(CONFIG_TEGRA2) -/* - * Setup vector: - * (OMAP4 spl TEXT_BASE is not 32 byte aligned. - * Continue to use ROM code vector only in OMAP4 spl) - */ -#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) - /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ - mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register - bic r0, #CR_V @ V = 0 - mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register - - /* Set vector address in CP15 VBAR register */ - ldr r0, =_start - mcr p15, 0, r0, c12, c0, 0 @Set VBAR -#endif -#endif /* !Tegra2 */ - - /* the mask ROM code should have PLL and others stable */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT - /* - * FIXME(dhendrix): Do we need to explicitly disable icache/dcache - * first? See example 15-3 in Cortex-A programmers guide... - */ - bl cpu_init_cp15 - bl cpu_init_crit -#endif - -/* Set stackpointer in internal RAM to call board_init_f */ -call_board_init_f: - ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) - bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ - ldr r0,=0x00000000 - bl board_init_f - -/*------------------------------------------------------------------------------*/ - -/* - * void relocate_code (addr_sp, gd, addr_moni) - * - * This "function" does not return, instead it continues in RAM - * after relocating the monitor code. - * - */ - .globl relocate_code -relocate_code: - mov r4, r0 /* save addr_sp */ - mov r5, r1 /* save addr of gd */ - mov r6, r2 /* save addr of destination */ - - /* Set up the stack */ -stack_setup: - mov sp, r4 - - adr r0, _start - subs r9, r6, r0 /* r9 <- relocation offset */ - beq clear_bss /* skip relocation */ - mov r1, r6 /* r1 <- scratch for copy_loop */ - ldr r3, _image_copy_end_ofs - add r2, r0, r3 /* r2 <- source end address */ - -copy_loop: - ldmia r0!, {r9-r10} /* copy from source address [r0] */ - stmia r1!, {r9-r10} /* copy to target address [r1] */ - cmp r0, r2 /* until source end address [r2] */ - blo copy_loop - -#ifndef CONFIG_SPL_BUILD - /* - * fix .rel.dyn relocations - */ - ldr r0, _TEXT_BASE /* r0 <- Text base */ - sub r9, r6, r0 /* r9 <- relocation offset */ - ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ - add r10, r10, r0 /* r10 <- sym table in FLASH */ - ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ - add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ - ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ - add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ -fixloop: - ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ - add r0, r0, r9 /* r0 <- location to fix up in RAM */ - ldr r1, [r2, #4] - and r7, r1, #0xff - cmp r7, #23 /* relative fixup? */ - beq fixrel - cmp r7, #2 /* absolute fixup? */ - beq fixabs - /* ignore unknown type of fixup */ - b fixnext -fixabs: - /* absolute fix: set location to (offset) symbol value */ - mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ - add r1, r10, r1 /* r1 <- address of symbol in table */ - ldr r1, [r1, #4] /* r1 <- symbol value */ - add r1, r1, r9 /* r1 <- relocated sym addr */ - b fixnext -fixrel: - /* relative fix: increase location by offset */ - ldr r1, [r0] - add r1, r1, r9 -fixnext: - str r1, [r0] - add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ - cmp r2, r3 - blo fixloop - b clear_bss -_rel_dyn_start_ofs: - .word __rel_dyn_start - _start -_rel_dyn_end_ofs: - .word __rel_dyn_end - _start -_dynsym_start_ofs: - .word __dynsym_start - _start - -#endif /* #ifndef CONFIG_SPL_BUILD */ - -clear_bss: -#ifdef CONFIG_SPL_BUILD - /* No relocation for SPL */ - ldr r0, =_bss - ldr r1, =_ebss -#else - ldr r0, _bss_start_ofs - ldr r1, _bss_end_ofs - mov r4, r6 /* reloc addr */ - add r0, r0, r4 - add r1, r1, r4 -#endif - mov r2, #0x00000000 /* clear */ - -clbss_l:str r2, [r0] /* clear loop... */ - add r0, r0, #4 - cmp r0, r1 - bne clbss_l - -/* - * We are done. Do not return, instead branch to second part of board - * initialization, now running from RAM. - */ -jump_2_ram: -/* - * If I-cache is enabled invalidate it - */ -#ifndef CONFIG_SYS_ICACHE_OFF - mcr p15, 0, r0, c7, c5, 0 @ invalidate icache - mcr p15, 0, r0, c7, c10, 4 @ DSB - mcr p15, 0, r0, c7, c5, 4 @ ISB -#endif - ldr r0, _board_init_r_ofs - adr r1, _start - add lr, r0, r1 - add lr, lr, r9 - /* setup parameters for board_init_r */ - mov r0, r5 /* gd_t */ - mov r1, r6 /* dest_addr */ - /* jump to it ... */ - mov pc, lr - -_board_init_r_ofs: - .word board_init_r - _start - -/************************************************************************* - * - * cpu_init_cp15 - * - * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless - * CONFIG_SYS_ICACHE_OFF is defined. - * - *************************************************************************/ -.globl cpu_init_cp15 -cpu_init_cp15: - /* - * Invalidate L1 I/D - */ - mov r0, #0 @ set up for MCR - mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs - mcr p15, 0, r0, c7, c5, 0 @ invalidate icache - mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array - mcr p15, 0, r0, c7, c10, 4 @ DSB - mcr p15, 0, r0, c7, c5, 4 @ ISB - - /* - * disable MMU stuff and caches - */ - mrc p15, 0, r0, c1, c0, 0 - bic r0, r0, #0x00002000 @ clear bits 13 (--V-) - bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) - orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB -#ifdef CONFIG_SYS_ICACHE_OFF - bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache -#else - orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache -#endif - mcr p15, 0, r0, c1, c0, 0 - mov pc, lr @ back to my caller - - -#ifndef CONFIG_SKIP_LOWLEVEL_INIT -/************************************************************************* - * - * CPU_init_critical registers - * - * setup important registers - * setup memory timing - * - *************************************************************************/ -cpu_init_crit: - /* - * Jump to board specific initialization... - * The Mask ROM will have already initialized - * basic memory. Go here to bump up clock rate and handle - * wake up conditions. - */ - mov ip, lr @ persevere link reg across call - bl lowlevel_init @ go setup pll,mux,memory - mov lr, ip @ restore link - mov pc, lr @ back to my caller -#endif - -#ifndef CONFIG_SPL_BUILD -/* - ************************************************************************* - * - * Interrupt handling - * - ************************************************************************* - */ -@ -@ IRQ stack frame. -@ -#define S_FRAME_SIZE 72 - -#define S_OLD_R0 68 -#define S_PSR 64 -#define S_PC 60 -#define S_LR 56 -#define S_SP 52 - -#define S_IP 48 -#define S_FP 44 -#define S_R10 40 -#define S_R9 36 -#define S_R8 32 -#define S_R7 28 -#define S_R6 24 -#define S_R5 20 -#define S_R4 16 -#define S_R3 12 -#define S_R2 8 -#define S_R1 4 -#define S_R0 0 - -#define MODE_SVC 0x13 -#define I_BIT 0x80 - -/* - * use bad_save_user_regs for abort/prefetch/undef/swi ... - * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling - */ - - .macro bad_save_user_regs - sub sp, sp, #S_FRAME_SIZE @ carve out a frame