xref: /kernel/liteos_a/kernel/common/los_printf.c (revision 0d163575)
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 *    conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 *    of conditions and the following disclaimer in the documentation and/or other materials
13 *    provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 *    to endorse or promote products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "los_base.h"
33#ifdef LOSCFG_LIB_LIBC
34#include "stdlib.h"
35#include "unistd.h"
36#endif
37#include "los_hwi.h"
38#include "los_memory_pri.h"
39#include "los_process_pri.h"
40#ifdef LOSCFG_FS_VFS
41#include "console.h"
42#endif
43#ifdef LOSCFG_SHELL_DMESG
44#include "dmesg_pri.h"
45#endif
46#ifdef LOSCFG_SAVE_EXCINFO
47#include "los_excinfo_pri.h"
48#endif
49#include "los_exc_pri.h"
50#include "los_sched_pri.h"
51
52#define SIZEBUF  256
53
54const CHAR *g_logString[] = {
55    "EMG",
56    "COMMON",
57    "ERR",
58    "WARN",
59    "INFO",
60    "DEBUG",
61    "TRACE"
62};
63
64const CHAR *OsLogLvGet(INT32 level)
65{
66    return g_logString[level];
67}
68
69STATIC VOID ErrorMsg(VOID)
70{
71    const CHAR *p = "Output illegal string! vsnprintf_s failed!\n";
72    UartPuts(p, (UINT32)strlen(p), UART_WITH_LOCK);
73}
74
75STATIC VOID UartOutput(const CHAR *str, UINT32 len, BOOL isLock)
76{
77#ifdef LOSCFG_SHELL_DMESG
78    if (!OsCheckUartLock()) {
79        UartPuts(str, len, isLock);
80    }
81    if (isLock != UART_WITHOUT_LOCK) {
82        (VOID)OsLogMemcpyRecord(str, len);
83    }
84#else
85    UartPuts(str, len, isLock);
86#endif
87}
88
89#ifdef LOSCFG_PLATFORM_CONSOLE
90STATIC VOID ConsoleOutput(const CHAR *str, UINT32 len)
91{
92    ssize_t written = 0;
93    ssize_t cnt;
94    ssize_t toWrite = len;
95
96    for (;;) {
97        cnt = write(STDOUT_FILENO, str + written, (size_t)toWrite);
98        if ((cnt < 0) || ((cnt == 0) && ((!OsPreemptable()) || (OS_INT_ACTIVE))) || (toWrite == cnt)) {
99            break;
100        }
101        written += cnt;
102        toWrite -= cnt;
103    }
104}
105#endif
106
107VOID OutputControl(const CHAR *str, UINT32 len, OutputType type)
108{
109    switch (type) {
110        case CONSOLE_OUTPUT:
111#ifdef LOSCFG_PLATFORM_CONSOLE
112            if (ConsoleEnable() == TRUE) {
113                ConsoleOutput(str, len);
114                break;
115            }
116#endif
117            /* fall-through */
118        case UART_OUTPUT:
119            UartOutput(str, len, UART_WITH_LOCK);
120            break;
121        case EXC_OUTPUT:
122            UartPuts(str, len, UART_WITH_LOCK);
123            break;
124        default:
125            break;
126    }
127    return;
128}
129
130STATIC VOID OsVprintfFree(CHAR *buf, UINT32 bufLen)
131{
132    if (bufLen != SIZEBUF) {
133        (VOID)LOS_MemFree(m_aucSysMem0, buf);
134    }
135}
136
137VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type)
138{
139    INT32 len;
140    const CHAR *errMsgMalloc = "OsVprintf, malloc failed!\n";
141    const CHAR *errMsgLen = "OsVprintf, length overflow!\n";
142    CHAR aBuf[SIZEBUF] = {0};
143    CHAR *bBuf = NULL;
144    UINT32 bufLen = SIZEBUF;
145    UINT32 systemStatus;
146
147    bBuf = aBuf;
148    len = vsnprintf_s(bBuf, bufLen, bufLen - 1, fmt, ap);
149    if ((len == -1) && (*bBuf == '\0')) {
150        /* parameter is illegal or some features in fmt dont support */
151        ErrorMsg();
152        return;
153    }
154
155    while (len == -1) {
156        /* bBuf is not enough */
157        OsVprintfFree(bBuf, bufLen);
158
159        bufLen = bufLen << 1;
160        if ((INT32)bufLen <= 0) {
161            UartPuts(errMsgLen, (UINT32)strlen(errMsgLen), UART_WITH_LOCK);
162            return;
163        }
164        bBuf = (CHAR *)LOS_MemAlloc(m_aucSysMem0, bufLen);
165        if (bBuf == NULL) {
166            UartPuts(errMsgMalloc, (UINT32)strlen(errMsgMalloc), UART_WITH_LOCK);
167            return;
168        }
169        len = vsnprintf_s(bBuf, bufLen, bufLen - 1, fmt, ap);
170        if (*bBuf == '\0') {
171            /* parameter is illegal or some features in fmt dont support */
172            (VOID)LOS_MemFree(m_aucSysMem0, bBuf);
173            ErrorMsg();
174            return;
175        }
176    }
177    *(bBuf + len) = '\0';
178
179    systemStatus = OsGetSystemStatus();
180    if ((systemStatus == OS_SYSTEM_NORMAL) || (systemStatus == OS_SYSTEM_EXC_OTHER_CPU)) {
181        OutputControl(bBuf, len, type);
182    } else if (systemStatus == OS_SYSTEM_EXC_CURR_CPU) {
183        OutputControl(bBuf, len, EXC_OUTPUT);
184    }
185    OsVprintfFree(bBuf, bufLen);
186}
187
188VOID UartVprintf(const CHAR *fmt, va_list ap)
189{
190    OsVprintf(fmt, ap, UART_OUTPUT);
191}
192
193__attribute__((noinline)) VOID UartPrintf(const CHAR *fmt, ...)
194{
195    va_list ap;
196    va_start(ap, fmt);
197    OsVprintf(fmt, ap, UART_OUTPUT);
198    va_end(ap);
199}
200
201#ifndef LOSCFG_LIBC_NEWLIB
202__attribute__((noinline)) VOID dprintf(const CHAR *fmt, ...)
203{
204    va_list ap;
205    va_start(ap, fmt);
206    OsVprintf(fmt, ap, CONSOLE_OUTPUT);
207#ifdef LOSCFG_SAVE_EXCINFO
208    if (OsGetSystemStatus() == OS_SYSTEM_EXC_CURR_CPU) {
209        WriteExcBufVa(fmt, ap);
210    }
211#endif
212    va_end(ap);
213}
214#endif
215
216VOID LkDprintf(const CHAR *fmt, va_list ap)
217{
218    OsVprintf(fmt, ap, CONSOLE_OUTPUT);
219#ifdef LOSCFG_SAVE_EXCINFO
220    if (OsGetSystemStatus() == OS_SYSTEM_EXC_CURR_CPU) {
221        WriteExcBufVa(fmt, ap);
222    }
223#endif
224}
225
226#ifdef LOSCFG_SHELL_DMESG
227VOID DmesgPrintf(const CHAR *fmt, va_list ap)
228{
229    OsVprintf(fmt, ap, CONSOLE_OUTPUT);
230}
231#endif
232
233#ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
234__attribute__((noinline)) INT32 printf(const CHAR *fmt, ...)
235{
236    va_list ap;
237    va_start(ap, fmt);
238    OsVprintf(fmt, ap, UART_OUTPUT);
239    va_end(ap);
240    return 0;
241}
242#endif
243
244__attribute__((noinline)) VOID syslog(INT32 level, const CHAR *fmt, ...)
245{
246    va_list ap;
247    va_start(ap, fmt);
248    OsVprintf(fmt, ap, CONSOLE_OUTPUT);
249    va_end(ap);
250    (VOID)level;
251}
252
253__attribute__((noinline)) VOID ExcPrintf(const CHAR *fmt, ...)
254{
255    va_list ap;
256    va_start(ap, fmt);
257    /* uart output without print-spinlock */
258    OsVprintf(fmt, ap, EXC_OUTPUT);
259    va_end(ap);
260}
261
262VOID PrintExcInfo(const CHAR *fmt, ...)
263{
264    va_list ap;
265    va_start(ap, fmt);
266    /* uart output without print-spinlock */
267    OsVprintf(fmt, ap, EXC_OUTPUT);
268#ifdef LOSCFG_SAVE_EXCINFO
269    WriteExcBufVa(fmt, ap);
270#endif
271    va_end(ap);
272}
273
274#ifndef LOSCFG_SHELL_LK
275VOID LOS_LkPrint(INT32 level, const CHAR *func, INT32 line, const CHAR *fmt, ...)
276{
277    va_list ap;
278
279    if (level > PRINT_LEVEL) {
280        return;
281    }
282
283    if ((level != LOS_COMMON_LEVEL) && ((level > LOS_EMG_LEVEL) && (level <= LOS_TRACE_LEVEL))) {
284        PRINTK("[%s][%s:%s]", g_logString[level],
285                ((OsCurrProcessGet() == NULL) ? "NULL" : OsCurrProcessGet()->processName),
286                ((OsCurrTaskGet() == NULL) ? "NULL" : OsCurrTaskGet()->taskName));
287    }
288
289    va_start(ap, fmt);
290    OsVprintf(fmt, ap, CONSOLE_OUTPUT);
291#ifdef LOSCFG_SAVE_EXCINFO
292    if (OsGetSystemStatus() == OS_SYSTEM_EXC_CURR_CPU) {
293        WriteExcBufVa(fmt, ap);
294    }
295#endif
296    va_end(ap);
297}
298#endif
299
300