1// Copyright 2016 The Fuchsia Authors
2// Copyright (c) 2008-2015 Travis Geiselbrecht
3//
4// Use of this source code is governed by a MIT-style
5// license that can be found in the LICENSE file or at
6// https://opensource.org/licenses/MIT
7
8#include <arch/ops.h>
9#include <ctype.h>
10#include <debug.h>
11#include <dev/hw_rng.h>
12#include <kernel/spinlock.h>
13#include <list.h>
14#include <platform.h>
15#include <platform/debug.h>
16#include <printf.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <zircon/types.h>
20#include <zircon/time.h>
21
22void spin(uint32_t usecs) {
23    zx_time_t start = current_time();
24
25    zx_duration_t nsecs = ZX_USEC(usecs);
26    while (zx_time_sub_time(current_time(), start) < nsecs)
27        ;
28}
29
30void _panic(void* caller, void* frame, const char* fmt, ...) {
31    platform_panic_start();
32
33    printf("panic (caller %p frame %p): ", caller, frame);
34
35    va_list ap;
36    va_start(ap, fmt);
37    vprintf(fmt, ap);
38    va_end(ap);
39
40    platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
41}
42
43static void puts_for_panic(const char *msg, size_t len)
44{
45    __printf_output_func(msg, len, NULL);
46}
47
48void _panic_no_format(const char *msg, size_t len) {
49    platform_panic_start();
50    puts_for_panic(msg, len);
51    platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
52}
53
54void __stack_chk_fail(void) {
55    panic_no_format("stack canary corrupted!\n");
56}
57
58uintptr_t choose_stack_guard(void) {
59    uintptr_t guard;
60    if (hw_rng_get_entropy(&guard, sizeof(guard), true) != sizeof(guard)) {
61        // We can't get a random value, so use a randomish value.
62        guard = 0xdeadbeef00ff00ffUL ^ (uintptr_t)&guard;
63    }
64    return guard;
65}
66
67#if !DISABLE_DEBUG_OUTPUT
68
69void hexdump_very_ex(const void* ptr, size_t len, uint64_t disp_addr, hexdump_print_fn_t* pfn) {
70    addr_t address = (addr_t)ptr;
71    size_t count;
72
73    for (count = 0; count < len; count += 16) {
74        union {
75            uint32_t buf[4];
76            uint8_t cbuf[16];
77        } u;
78        size_t s = ROUNDUP(MIN(len - count, 16), 4);
79        size_t i;
80
81        pfn(((disp_addr + len) > 0xFFFFFFFF)
82                ? "0x%016llx: "
83                : "0x%08llx: ",
84            disp_addr + count);
85
86        for (i = 0; i < s / 4; i++) {
87            u.buf[i] = ((const uint32_t*)address)[i];
88            pfn("%08x ", u.buf[i]);
89        }
90        for (; i < 4; i++) {
91            pfn("         ");
92        }
93        pfn("|");
94
95        for (i = 0; i < 16; i++) {
96            char c = u.cbuf[i];
97            if (i < s && isprint(c)) {
98                pfn("%c", c);
99            } else {
100                pfn(".");
101            }
102        }
103        pfn("|\n");
104        address += 16;
105    }
106}
107
108void hexdump8_very_ex(const void* ptr, size_t len, uint64_t disp_addr, hexdump_print_fn_t* pfn) {
109    addr_t address = (addr_t)ptr;
110    size_t count;
111    size_t i;
112
113    for (count = 0; count < len; count += 16) {
114        pfn(((disp_addr + len) > 0xFFFFFFFF)
115                ? "0x%016llx: "
116                : "0x%08llx: ",
117            disp_addr + count);
118
119        for (i = 0; i < MIN(len - count, 16); i++) {
120            pfn("%02hhx ", *(const uint8_t*)(address + i));
121        }
122
123        for (; i < 16; i++) {
124            pfn("   ");
125        }
126
127        pfn("|");
128
129        for (i = 0; i < MIN(len - count, 16); i++) {
130            char c = ((const char*)address)[i];
131            pfn("%c", isprint(c) ? c : '.');
132        }
133
134        pfn("\n");
135        address += 16;
136    }
137}
138
139#endif // !DISABLE_DEBUG_OUTPUT
140