1 // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 /*
3  * Misc utility functions
4  *
5  * Copyright 2013-2018 IBM Corp.
6  */
7 
8 #include <skiboot.h>
9 #include <lock.h>
10 #include <fsp.h>
11 #include <platform.h>
12 #include <processor.h>
13 #include <cpu.h>
14 #include <stack.h>
15 
assert_fail(const char * msg,const char * file,unsigned int line,const char * function)16 void __noreturn assert_fail(const char *msg, const char *file,
17 				unsigned int line, const char *function)
18 {
19 	static bool in_abort = false;
20 
21 	(void)function;
22 	if (in_abort)
23 		for (;;) ;
24 	in_abort = true;
25 
26 	/**
27 	 * @fwts-label FailedAssert2
28 	 * @fwts-advice OPAL hit an assert(). During normal usage (even
29 	 * testing) we should never hit an assert. There are other code
30 	 * paths for controlled shutdown/panic in the event of catastrophic
31 	 * errors.
32 	 */
33 	prlog(PR_EMERG, "assert failed at %s:%u: %s\n", file, line, msg);
34 	backtrace();
35 
36 	if (platform.terminate)
37 		platform.terminate(msg);
38 
39 	for (;;) ;
40 }
41 
tohex(uint8_t nibble)42 char __attrconst tohex(uint8_t nibble)
43 {
44 	static const char __tohex[] = {'0','1','2','3','4','5','6','7','8','9',
45 				       'A','B','C','D','E','F'};
46 	if (nibble > 0xf)
47 		return '?';
48 	return __tohex[nibble];
49 }
50 
get_symbol(unsigned long addr,char ** sym,char ** sym_end)51 static unsigned long get_symbol(unsigned long addr, char **sym, char **sym_end)
52 {
53 	unsigned long prev = 0, next;
54 	char *psym = NULL, *p = __sym_map_start;
55 
56 	*sym = *sym_end = NULL;
57 	while(p < __sym_map_end) {
58 		next = strtoul(p, &p, 16) | SKIBOOT_BASE;
59 		if (next > addr && prev <= addr) {
60 			p = psym + 3;;
61 			if (p >= __sym_map_end)
62 				return 0;
63 			*sym = p;
64 			while(p < __sym_map_end && *p != 10)
65 				p++;
66 			*sym_end = p;
67 			return prev;
68 		}
69 		prev = next;
70 		psym = p;
71 		while(p < __sym_map_end && *p != 10)
72 			p++;
73 		p++;
74 	}
75 	return 0;
76 }
77 
snprintf_symbol(char * buf,size_t len,uint64_t addr)78 size_t snprintf_symbol(char *buf, size_t len, uint64_t addr)
79 {
80 	unsigned long saddr;
81 	char *sym, *sym_end;
82 	size_t l;
83 
84 	saddr = get_symbol(addr, &sym, &sym_end);
85 	if (!saddr)
86 		return 0;
87 
88 	if (len > sym_end - sym)
89 		l = sym_end - sym;
90 	else
91 		l = len - 1;
92 	memcpy(buf, sym, l);
93 
94 	/*
95 	 * This snprintf will insert the terminating NUL even if the
96 	 * symbol has used up the entire buffer less 1.
97 	 */
98 	l += snprintf(buf + l, len - l, "+0x%llx", addr - saddr);
99 
100 	return l;
101 }
102