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