blob: 93d6bfc41276a5eedf1467f346d1ae298d0cc697 [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauereca92fb2006-08-23 14:28:37 +00002
Stefan Reinauer55259bd2010-02-28 18:13:09 +00003#ifndef __ASSERT_H__
4#define __ASSERT_H__
Uwe Hermannc70e9fc2010-02-15 23:10:19 +00005
Julius Wernerd82e0cf2015-02-17 17:27:23 -08006#include <arch/hlt.h>
Hung-Te Lin34c59332014-02-21 16:22:52 +08007#include <console/console.h>
Elyes HAOUAS5817c562020-07-12 09:03:22 +02008#include <stdint.h>
Hung-Te Lin34c59332014-02-21 16:22:52 +08009
Julius Wernera73e5a72019-05-09 14:12:17 -070010/* TODO: Fix vendorcode headers to not define macros coreboot uses or to be more
11 properly isolated. */
12#ifdef ASSERT
13#undef ASSERT
14#endif
15
Angel Pons46451972020-06-08 15:52:03 +020016/* Do not use filenames nor line numbers on timeless builds, to preserve reproducibility */
17#if ENV_TIMELESS
18#define __ASSERT_FILE__ "(filenames not available on timeless builds)"
19#define __ASSERT_LINE__ 404
20#else
21#define __ASSERT_FILE__ __FILE__
22#define __ASSERT_LINE__ __LINE__
23#endif
24
Julius Werner2aedc972020-07-29 16:55:18 -070025#ifndef _PORTING_H_ /* TODO: Isolate AGESA properly. */
26#define __build_time_assert(x) \
27 (__builtin_constant_p(x) ? ((x) ? 1 : dead_code_t(int)) : 0)
28#else
29#define __build_time_assert(x) 0
30#endif
31
Jakub Czapiga45d37d52021-03-25 14:28:29 +010032/* CMocka function redefinition. */
33void mock_assert(const int result, const char *const expression,
34 const char *const file, const int line);
35
36#if ENV_TEST
37#define MOCK_ASSERT(result, expression) \
38 mock_assert((result), (expression), __ASSERT_FILE__, __ASSERT_LINE__)
39#else
40#define MOCK_ASSERT(result, expression)
41#endif
42
Stefan Reinauer55259bd2010-02-28 18:13:09 +000043/* GCC and CAR versions */
Angel Pons46451972020-06-08 15:52:03 +020044#define ASSERT(x) { \
Julius Werner2aedc972020-07-29 16:55:18 -070045 if (!__build_time_assert(x) && !(x)) { \
Angel Pons46451972020-06-08 15:52:03 +020046 printk(BIOS_EMERG, \
47 "ASSERTION ERROR: file '%s', line %d\n", \
48 __ASSERT_FILE__, __ASSERT_LINE__); \
Jakub Czapiga45d37d52021-03-25 14:28:29 +010049 MOCK_ASSERT(!!(x), #x); \
Angel Pons46451972020-06-08 15:52:03 +020050 if (CONFIG(FATAL_ASSERTS)) \
51 hlt(); \
52 } \
Stefan Reinauer55259bd2010-02-28 18:13:09 +000053}
Angel Pons46451972020-06-08 15:52:03 +020054#define ASSERT_MSG(x, msg) { \
Julius Werner2aedc972020-07-29 16:55:18 -070055 if (!__build_time_assert(x) && !(x)) { \
Angel Pons46451972020-06-08 15:52:03 +020056 printk(BIOS_EMERG, \
57 "ASSERTION ERROR: file '%s', line %d\n", \
58 __ASSERT_FILE__, __ASSERT_LINE__); \
59 printk(BIOS_EMERG, "%s", msg); \
Jakub Czapiga45d37d52021-03-25 14:28:29 +010060 MOCK_ASSERT(!!(x), (msg)); \
Angel Pons46451972020-06-08 15:52:03 +020061 if (CONFIG(FATAL_ASSERTS)) \
62 hlt(); \
63 } \
Eric Peers9d495982019-12-17 10:02:15 -070064}
Angel Pons46451972020-06-08 15:52:03 +020065#define BUG() { \
66 printk(BIOS_EMERG, \
67 "ERROR: BUG ENCOUNTERED at file '%s', line %d\n", \
68 __ASSERT_FILE__, __ASSERT_LINE__); \
Jakub Czapiga45d37d52021-03-25 14:28:29 +010069 MOCK_ASSERT(0, "BUG ENCOUNTERED"); \
Angel Pons46451972020-06-08 15:52:03 +020070 if (CONFIG(FATAL_ASSERTS)) \
71 hlt(); \
Stefan Reinauer55259bd2010-02-28 18:13:09 +000072}
73
Hung-Te Lin34c59332014-02-21 16:22:52 +080074#define assert(statement) ASSERT(statement)
Uwe Hermann2bb4acf2010-03-01 17:19:55 +000075
Julius Wernerb8534f72017-07-14 14:14:11 -070076/*
77 * These macros can be used to assert that a certain branch of code is dead and
78 * will be compile-time eliminated. This differs from _Static_assert(), which
79 * will generate a compiler error even if the scope it was called from is dead
80 * code. This may be useful to double-check things like constants that are only
81 * valid if a certain Kconfig option is set.
Julius Werner988ac292019-03-28 13:39:06 -070082 *
83 * The error message when this hits will look like this:
84 *
85 * ramstage/lib/bootmode.o: In function `display_init_required':
Nico Huberdb2c8df2020-04-06 23:02:12 +020086 * bootmode.c:42: undefined reference to `_dead_code_assertion_failed'
Julius Wernerb8534f72017-07-14 14:14:11 -070087 */
Nico Huberdb2c8df2020-04-06 23:02:12 +020088extern void _dead_code_assertion_failed(void) __attribute__((noreturn));
89#define dead_code() _dead_code_assertion_failed()
Julius Wernerb8534f72017-07-14 14:14:11 -070090
91/* This can be used in the context of an expression of type 'type'. */
Julius Werner988ac292019-03-28 13:39:06 -070092#define dead_code_t(type) ({ \
93 dead_code(); \
Julius Wernerb8534f72017-07-14 14:14:11 -070094 *(type *)(uintptr_t)0; \
95})
96
Patrick Rudolphadcf7822020-08-27 20:50:18 +020097#if ENV_X86_64
Patrick Rudolphe5638152018-12-09 10:48:59 +010098#define pointer_to_uint32_safe(x) ({ \
99 if ((uintptr_t)(x) > 0xffffffffUL) \
100 die("Cast from pointer to uint32_t overflows"); \
101 (uint32_t)(uintptr_t)(x); \
102})
103#else
104#define pointer_to_uint32_safe(x) ({ \
105 (uint32_t)(uintptr_t)(x); \
106})
107#endif
Uwe Hermann2bb4acf2010-03-01 17:19:55 +0000108#endif // __ASSERT_H__