1 /* Copyright 2013-2014 IBM Corp.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * 	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <skiboot.h>
18 #include <lock.h>
19 #include <fsp.h>
20 #include <platform.h>
21 #include <processor.h>
22 #include <cpu.h>
23 #include <stack.h>
24 
assert_fail(const char * msg)25 void __noreturn assert_fail(const char *msg)
26 {
27 	/**
28 	 * @fwts-label FailedAssert
29 	 * @fwts-advice OPAL hit an assert(). During normal usage (even
30 	 * testing) we should never hit an assert. There are other code
31 	 * paths for controlled shutdown/panic in the event of catastrophic
32 	 * errors.
33 	 */
34 	prlog(PR_EMERG, "Assert fail: %s\n", msg);
35 	_abort(msg);
36 }
37 
_abort(const char * msg)38 void __noreturn _abort(const char *msg)
39 {
40 	static bool in_abort = false;
41 
42 	if (in_abort)
43 		for (;;) ;
44 	in_abort = true;
45 
46 	prlog(PR_EMERG, "Aborting!\n");
47 	backtrace();
48 
49 	if (platform.terminate)
50 		platform.terminate(msg);
51 
52 	for (;;) ;
53 }
54 
tohex(uint8_t nibble)55 char __attrconst tohex(uint8_t nibble)
56 {
57 	static const char __tohex[] = {'0','1','2','3','4','5','6','7','8','9',
58 				       'A','B','C','D','E','F'};
59 	if (nibble > 0xf)
60 		return '?';
61 	return __tohex[nibble];
62 }
63 
get_symbol(unsigned long addr,char ** sym,char ** sym_end)64 static unsigned long get_symbol(unsigned long addr, char **sym, char **sym_end)
65 {
66 	unsigned long prev = 0, next;
67 	char *psym = NULL, *p = __sym_map_start;
68 
69 	*sym = *sym_end = NULL;
70 	while(p < __sym_map_end) {
71 		next = strtoul(p, &p, 16) | SKIBOOT_BASE;
72 		if (next > addr && prev <= addr) {
73 			p = psym + 3;;
74 			if (p >= __sym_map_end)
75 				return 0;
76 			*sym = p;
77 			while(p < __sym_map_end && *p != 10)
78 				p++;
79 			*sym_end = p;
80 			return prev;
81 		}
82 		prev = next;
83 		psym = p;
84 		while(p < __sym_map_end && *p != 10)
85 			p++;
86 		p++;
87 	}
88 	return 0;
89 }
90 
snprintf_symbol(char * buf,size_t len,uint64_t addr)91 size_t snprintf_symbol(char *buf, size_t len, uint64_t addr)
92 {
93 	unsigned long saddr;
94 	char *sym, *sym_end;
95 	size_t l;
96 
97 	saddr = get_symbol(addr, &sym, &sym_end);
98 	if (!saddr)
99 		return 0;
100 
101 	if (len > sym_end - sym)
102 		l = sym_end - sym;
103 	else
104 		l = len - 1;
105 	memcpy(buf, sym, l);
106 
107 	/*
108 	 * This snprintf will insert the terminating NUL even if the
109 	 * symbol has used up the entire buffer less 1.
110 	 */
111 	l += snprintf(buf + l, len - l, "+0x%llx", addr - saddr);
112 
113 	return l;
114 }
115