summaryrefslogtreecommitdiff
path: root/cesar/hle/tools/src/debug_dump.c
blob: 9dfd4842a941159646ffe71086a183402c2a7231 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* Cesar project {{{
 *
 * Copyright (C) 2010 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    hle/tools/src/debug_dump.c
 * \brief   Handle debug dump over mailbox.
 * \ingroup hle
 *
 * This implements a debug dump over the mailbox to be used for fatal error
 * dumps.
 *
 * When a buffer is to be dumped, this codes reads all messages from mailbox
 * and only process debug messages.  If a message gives a debug buffer, it is
 * filled and sent back to ARM side.
 */
#include "common/std.h"

#include "hle/tools/tools.h"

#include "inc/context.h"

void
hle_tools_debug_dump_send_buffer (hle_tools_t *ctx,
                                  u32 *buffer, uint buffer_length)
{
    dbg_assert (ctx);
    dbg_assert (buffer);
    ipmbox_msg_mbx_t msg;
    msg.header = ipmbox_msg_create_header_debug_dump (buffer_length);
    msg.buffer_addr = (u32) buffer;
    ipmbox_tx_mbx (ctx->ipmbox, (u32 *) &msg, IPMBOX_MSG_MBX_WORDS);
}

/**
 * Synchronous dump to ARM side.
 * \param  user  user parameter (HLE tools context)
 * \param  text  text buffer with text to write
 * \param  text_size  size of text to write, or 0 for end of dump
 * \return  sent size
 */
int
hle_tools_dump (void *user, const char *text, uint text_size)
{
    const u32 *msg_buffer;
    uint msg_nb;
    ipmbox_msg_mbx_t *m, *m_end;
    uint type;
    u32 *buffer;
    uint buffer_length;
    uint dump, dumped;
    u32 w;
    uint wb;
    int sent = text_size;
    bool end_of_dump = text_size == 0;
    hle_tools_t *ctx = user;
    dbg_assert (ctx);
    /** Loop until satisfied. */
    while (text_size || end_of_dump)
    {
        /* Get mailbox content. */
        msg_nb = ipmbox_rx_sync (ctx->ipmbox, &msg_buffer)
            / IPMBOX_MSG_MBX_WORDS;
        m = (ipmbox_msg_mbx_t *) msg_buffer;
        m_end = m + msg_nb;
        /* Read messages. */
        for ( ; m != m_end; m++)
        {
            type = ipmbox_msg_get_mbx_type (m->header);
            switch (type)
            {
            case IPMBOX_MSG_MBX_TYPE_DEBUG_DUMP:
                /* Dump buffer. */
                buffer_length =
                    ipmbox_msg_get_debug_dump_length (m->header);
                buffer = (u32 *) m->buffer_addr;
                /* Fill it, little endian. */
                dumped = dump = MIN (text_size, buffer_length);
                for (; dump >= 4; dump -= 4)
                {
                    w = *text++;
                    w |= *text++ << 8;
                    w |= *text++ << 16;
                    w |= *text++ << 24;
                    *buffer++ = w;
                }
                w = 0; wb = 0;
                for (; dump; dump--)
                {
                    w |= *text++ << wb;
                    wb += 8;
                }
                if (wb)
                    *buffer++ = w;
                text_size -= dumped;
                /* Send back message. */
                hle_tools_debug_dump_send_buffer (
                    ctx, (u32 *) m->buffer_addr, dumped);
                /* Clear end_of_dump flag, it was sent. */
                end_of_dump = false;
                break;
            default:
                /* Forward to general tools. */
                hle_tools_msg_recv (ctx, m);
                break;
            }
        }
    }
    return sent;
}

void
hle_tools_debug_dump_init (hle_tools_t *ctx)
{
    dbg_register_dump_callback (hle_tools_dump, ctx);
}