• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "console.h"
33 #include "fcntl.h"
34 #include "sys/ioctl.h"
35 #ifdef LOSCFG_FILE_MODE
36 #include "stdarg.h"
37 #endif
38 #include "unistd.h"
39 #include "securec.h"
40 #ifdef LOSCFG_SHELL_DMESG
41 #include "dmesg_pri.h"
42 #endif
43 #ifdef LOSCFG_SHELL
44 #include "shcmd.h"
45 #include "shell_pri.h"
46 #endif
47 #include "los_exc_pri.h"
48 #include "los_process_pri.h"
49 #include "los_sched_pri.h"
50 #include "user_copy.h"
51 #include "fs/driver.h"
52 
53 #define EACH_CHAR 1
54 #define UART_IOC_MAGIC   'u'
55 #define UART_CFG_ATTR    _IOW(UART_IOC_MAGIC, 5, int)
56 #define UART_CFG_PRIVATE    _IOW(UART_IOC_MAGIC, 6, int)
57 /* Inter-module variable */
58 extern UINT32 g_uart_fputc_en;
59 STATIC UINT32 ConsoleSendTask(UINTPTR param);
60 
61 STATIC UINT8 g_taskConsoleIDArray[LOSCFG_BASE_CORE_TSK_LIMIT];
62 STATIC SPIN_LOCK_INIT(g_consoleSpin);
63 STATIC SPIN_LOCK_INIT(g_consoleWriteSpinLock);
64 
65 #define SHELL_ENTRYID_INVALID     0xFFFFFFFF
66 #define SHELL_TASK_PRIORITY       9
67 #define CONSOLE_CIRBUF_EVENT      0x02U
68 #define CONSOLE_SEND_TASK_EXIT    0x04U
69 #define CONSOLE_SEND_TASK_RUNNING 0x10U
70 
71 #define SHELL_ENTRY_NAME     "ShellEntry"
72 #define SHELL_ENTRY_NAME_LEN 10
73 
74 CONSOLE_CB *g_console[CONSOLE_NUM];
75 #define MIN(a, b) ((a) < (b) ? (a) : (b))
76 
77 /*
78  * acquire uart driver function and filep of /dev/console,
79  * then store uart driver function in *filepOps
80  * and store filep of /dev/console in *privFilep.
81  */
GetFilepOps(const struct file * filep,struct file ** privFilep,const struct file_operations_vfs ** filepOps)82 INT32 GetFilepOps(const struct file *filep, struct file **privFilep, const struct file_operations_vfs **filepOps)
83 {
84     INT32 ret;
85 
86     if ((filep == NULL) || (filep->f_vnode == NULL) || (filep->f_vnode->data == NULL)) {
87         ret = EINVAL;
88         goto ERROUT;
89     }
90 
91     /* to find console device's filep(now it is *privFilep) through i_private */
92     struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
93     *privFilep = (struct file *)drv->priv;
94     if (((*privFilep)->f_vnode == NULL) || ((*privFilep)->f_vnode->data == NULL)) {
95         ret = EINVAL;
96         goto ERROUT;
97     }
98 
99     /* to find uart driver operation function through u.i_opss */
100 
101     drv = (struct drv_data *)(*privFilep)->f_vnode->data;
102 
103     *filepOps = (const struct file_operations_vfs *)drv->ops;
104 
105     return ENOERR;
106 ERROUT:
107     set_errno(ret);
108     return VFS_ERROR;
109 }
110 
ConsoleTcGetAttr(INT32 fd,struct termios * termios)111 INT32 ConsoleTcGetAttr(INT32 fd, struct termios *termios)
112 {
113     struct file *filep = NULL;
114     CONSOLE_CB *consoleCB = NULL;
115 
116     INT32 ret = fs_getfilep(fd, &filep);
117     if (ret < 0) {
118         return -EPERM;
119     }
120 
121     consoleCB = (CONSOLE_CB *)filep->f_priv;
122     if (consoleCB == NULL) {
123         return -EFAULT;
124     }
125 
126     (VOID)memcpy_s(termios, sizeof(struct termios), &consoleCB->consoleTermios, sizeof(struct termios));
127     return LOS_OK;
128 }
129 
ConsoleTcSetAttr(INT32 fd,INT32 actions,const struct termios * termios)130 INT32 ConsoleTcSetAttr(INT32 fd, INT32 actions, const struct termios *termios)
131 {
132     struct file *filep = NULL;
133     CONSOLE_CB *consoleCB = NULL;
134 
135     (VOID)actions;
136 
137     INT32 ret = fs_getfilep(fd, &filep);
138     if (ret < 0) {
139         return -EPERM;
140     }
141 
142     consoleCB = (CONSOLE_CB *)filep->f_priv;
143     if (consoleCB == NULL) {
144         return -EFAULT;
145     }
146 
147     (VOID)memcpy_s(&consoleCB->consoleTermios, sizeof(struct termios), termios, sizeof(struct termios));
148     return LOS_OK;
149 }
150 
ConsoleRefcountGet(const CONSOLE_CB * consoleCB)151 STATIC UINT32 ConsoleRefcountGet(const CONSOLE_CB *consoleCB)
152 {
153     return consoleCB->refCount;
154 }
155 
ConsoleRefcountSet(CONSOLE_CB * consoleCB,BOOL flag)156 STATIC VOID ConsoleRefcountSet(CONSOLE_CB *consoleCB, BOOL flag)
157 {
158     (consoleCB->refCount) += flag ? 1 : -1;
159 }
160 
IsConsoleOccupied(const CONSOLE_CB * consoleCB)161 BOOL IsConsoleOccupied(const CONSOLE_CB *consoleCB)
162 {
163     return ConsoleRefcountGet(consoleCB);
164 }
165 
ConsoleCtrlCaptureLine(CONSOLE_CB * consoleCB)166 STATIC INT32 ConsoleCtrlCaptureLine(CONSOLE_CB *consoleCB)
167 {
168     struct termios consoleTermios = {0};
169     UINT32 intSave;
170 
171     LOS_SpinLockSave(&g_consoleSpin, &intSave);
172     (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
173     consoleTermios.c_lflag |= ICANON | ECHO;
174     (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
175     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
176 
177     return LOS_OK;
178 }
179 
ConsoleCtrlCaptureChar(CONSOLE_CB * consoleCB)180 STATIC INT32 ConsoleCtrlCaptureChar(CONSOLE_CB *consoleCB)
181 {
182     struct termios consoleTermios = {0};
183     UINT32 intSave;
184 
185     LOS_SpinLockSave(&g_consoleSpin, &intSave);
186     (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
187     consoleTermios.c_lflag &= ~(ICANON | ECHO);
188     (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
189     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
190 
191     return LOS_OK;
192 }
193 
ConsoleCtrlRightsCapture(CONSOLE_CB * consoleCB)194 STATIC INT32 ConsoleCtrlRightsCapture(CONSOLE_CB *consoleCB)
195 {
196     (VOID)LOS_SemPend(consoleCB->consoleSem, LOS_WAIT_FOREVER);
197     if ((ConsoleRefcountGet(consoleCB) == 0) &&
198         (OsCurrTaskGet()->taskID != consoleCB->shellEntryId)) {
199         /* not 0:indicate that shellentry is in uart_read, suspend shellentry task directly */
200         (VOID)LOS_TaskSuspend(consoleCB->shellEntryId);
201     }
202     ConsoleRefcountSet(consoleCB, TRUE);
203     return LOS_OK;
204 }
205 
ConsoleCtrlRightsRelease(CONSOLE_CB * consoleCB)206 STATIC INT32 ConsoleCtrlRightsRelease(CONSOLE_CB *consoleCB)
207 {
208     if (ConsoleRefcountGet(consoleCB) == 0) {
209         PRINT_ERR("console is free\n");
210         (VOID)LOS_SemPost(consoleCB->consoleSem);
211         return LOS_NOK;
212     } else {
213         ConsoleRefcountSet(consoleCB, FALSE);
214         if ((ConsoleRefcountGet(consoleCB) == 0) &&
215             (OsCurrTaskGet()->taskID != consoleCB->shellEntryId)) {
216             (VOID)LOS_TaskResume(consoleCB->shellEntryId);
217         }
218     }
219     (VOID)LOS_SemPost(consoleCB->consoleSem);
220     return LOS_OK;
221 }
222 
OsGetConsoleByDevice(const CHAR * deviceName)223 STATIC CONSOLE_CB *OsGetConsoleByDevice(const CHAR *deviceName)
224 {
225     INT32 ret;
226     struct Vnode *vnode = NULL;
227 
228     VnodeHold();
229     ret = VnodeLookup(deviceName, &vnode, 0);
230     VnodeDrop();
231     if (ret < 0) {
232         set_errno(EACCES);
233         return NULL;
234     }
235 
236     if (g_console[CONSOLE_SERIAL - 1]->devVnode == vnode) {
237         return g_console[CONSOLE_SERIAL - 1];
238     } else if (g_console[CONSOLE_TELNET - 1]->devVnode == vnode) {
239         return g_console[CONSOLE_TELNET - 1];
240     } else {
241         set_errno(ENOENT);
242         return NULL;
243     }
244 }
245 
OsGetConsoleID(const CHAR * deviceName)246 STATIC INT32 OsGetConsoleID(const CHAR *deviceName)
247 {
248     if ((deviceName != NULL) &&
249         (strlen(deviceName) == strlen(SERIAL)) &&
250         (!strncmp(deviceName, SERIAL, strlen(SERIAL)))) {
251         return CONSOLE_SERIAL;
252     }
253 #ifdef LOSCFG_NET_TELNET
254     else if ((deviceName != NULL) &&
255              (strlen(deviceName) == strlen(TELNET)) &&
256              (!strncmp(deviceName, TELNET, strlen(TELNET)))) {
257         return CONSOLE_TELNET;
258     }
259 #endif
260     return -1;
261 }
262 
OsConsoleFullpathToID(const CHAR * fullpath)263 STATIC INT32 OsConsoleFullpathToID(const CHAR *fullpath)
264 {
265 #define CONSOLE_SERIAL_1 "/dev/console1"
266 #define CONSOLE_TELNET_2 "/dev/console2"
267 
268     size_t len;
269 
270     if (fullpath == NULL) {
271         return -1;
272     }
273 
274     len = strlen(fullpath);
275     if ((len == strlen(CONSOLE_SERIAL_1)) &&
276         (!strncmp(fullpath, CONSOLE_SERIAL_1, strlen(CONSOLE_SERIAL_1)))) {
277         return CONSOLE_SERIAL;
278     }
279 #ifdef LOSCFG_NET_TELNET
280     else if ((len == strlen(CONSOLE_TELNET_2)) &&
281              (!strncmp(fullpath, CONSOLE_TELNET_2, strlen(CONSOLE_TELNET_2)))) {
282         return CONSOLE_TELNET;
283     }
284 #endif
285     return -1;
286 }
287 
ConsoleFifoEmpty(const CONSOLE_CB * console)288 STATIC BOOL ConsoleFifoEmpty(const CONSOLE_CB *console)
289 {
290     return console->fifoOut == console->fifoIn;
291 }
292 
ConsoleFifoClearup(CONSOLE_CB * console)293 STATIC VOID ConsoleFifoClearup(CONSOLE_CB *console)
294 {
295     console->fifoOut = 0;
296     console->fifoIn = 0;
297     (VOID)memset_s(console->fifo, CONSOLE_FIFO_SIZE, 0, CONSOLE_FIFO_SIZE);
298 }
299 
ConsoleFifoLenUpdate(CONSOLE_CB * console)300 STATIC VOID ConsoleFifoLenUpdate(CONSOLE_CB *console)
301 {
302     console->currentLen = console->fifoIn - console->fifoOut;
303 }
304 
ConsoleReadFifo(CHAR * buffer,CONSOLE_CB * console,size_t bufLen)305 STATIC INT32 ConsoleReadFifo(CHAR *buffer, CONSOLE_CB *console, size_t bufLen)
306 {
307     INT32 ret;
308     UINT32 readNum;
309 
310     readNum = MIN(bufLen, console->currentLen);
311     ret = memcpy_s(buffer, bufLen, console->fifo + console->fifoOut, readNum);
312     if (ret != EOK) {
313         PRINTK("%s,%d memcpy_s failed\n", __FUNCTION__, __LINE__);
314         return -1;
315     }
316     console->fifoOut += readNum;
317     if (ConsoleFifoEmpty(console)) {
318         ConsoleFifoClearup(console);
319     }
320     ConsoleFifoLenUpdate(console);
321     return (INT32)readNum;
322 }
323 
FilepOpen(struct file * filep,const struct file_operations_vfs * fops)324 INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops)
325 {
326     INT32 ret;
327     if (fops->open == NULL) {
328         return -EFAULT;
329     }
330 
331     /*
332      * adopt uart open function to open filep (filep is
333      * corresponding to filep of /dev/console)
334      */
335     ret = fops->open(filep);
336     return (ret < 0) ? -EPERM : ret;
337 }
338 
UserEndOfRead(CONSOLE_CB * consoleCB,struct file * filep,const struct file_operations_vfs * fops)339 STATIC INLINE VOID UserEndOfRead(CONSOLE_CB *consoleCB, struct file *filep,
340                                  const struct file_operations_vfs *fops)
341 {
342     CHAR ch;
343     if (consoleCB->consoleTermios.c_lflag & ECHO) {
344         ch = '\r';
345         (VOID)fops->write(filep, &ch, 1);
346     }
347     consoleCB->fifo[consoleCB->fifoIn++] = '\n';
348     consoleCB->fifo[consoleCB->fifoIn] = '\0';
349     consoleCB->currentLen = consoleCB->fifoIn;
350 }
351 
352 enum {
353     STAT_NORMAL_KEY,
354     STAT_ESC_KEY,
355     STAT_MULTI_KEY
356 };
357 
UserShellCheckUDRL(const CHAR ch,INT32 * lastTokenType)358 STATIC INT32 UserShellCheckUDRL(const CHAR ch, INT32 *lastTokenType)
359 {
360     INT32 ret = LOS_OK;
361     if (ch == 0x1b) { /* 0x1b: ESC */
362         *lastTokenType = STAT_ESC_KEY;
363         return ret;
364     } else if (ch == 0x5b) { /* 0x5b: first Key combination */
365         if (*lastTokenType == STAT_ESC_KEY) {
366             *lastTokenType = STAT_MULTI_KEY;
367             return ret;
368         }
369     } else if (ch == 0x41) { /* up */
370         if (*lastTokenType == STAT_MULTI_KEY) {
371             *lastTokenType = STAT_NORMAL_KEY;
372             return ret;
373         }
374     } else if (ch == 0x42) { /* down */
375         if (*lastTokenType == STAT_MULTI_KEY) {
376             *lastTokenType = STAT_NORMAL_KEY;
377             return ret;
378         }
379     } else if (ch == 0x43) { /* right */
380         if (*lastTokenType == STAT_MULTI_KEY) {
381             *lastTokenType = STAT_NORMAL_KEY;
382             return ret;
383         }
384     } else if (ch == 0x44) { /* left */
385         if (*lastTokenType == STAT_MULTI_KEY) {
386             *lastTokenType = STAT_NORMAL_KEY;
387             return ret;
388         }
389     }
390     return LOS_NOK;
391 }
392 
IsNeedContinue(CONSOLE_CB * consoleCB,char ch,INT32 * lastTokenType)393 STATIC INT32 IsNeedContinue(CONSOLE_CB *consoleCB, char ch, INT32 *lastTokenType)
394 {
395     if (((ch == '\b') && (consoleCB->consoleTermios.c_lflag & ECHO) && (ConsoleFifoEmpty(consoleCB))) ||
396         (UserShellCheckUDRL(ch, lastTokenType) == LOS_OK)) { /* parse the up/down/right/left key */
397         return LOS_NOK;
398     }
399 
400     return LOS_OK;
401 }
402 
EchoToTerminal(CONSOLE_CB * consoleCB,struct file * filep,const struct file_operations_vfs * fops,char ch)403 STATIC VOID EchoToTerminal(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, char ch)
404 {
405     if (consoleCB->consoleTermios.c_lflag & ECHO) {
406         if (ch == '\b') {
407             (VOID)fops->write(filep, "\b \b", 3); // 3: length of "\b \b"
408         } else {
409             (VOID)fops->write(filep, &ch, EACH_CHAR);
410         }
411     }
412 }
413 
StoreReadChar(CONSOLE_CB * consoleCB,char ch,INT32 readcount)414 STATIC VOID StoreReadChar(CONSOLE_CB *consoleCB, char ch, INT32 readcount)
415 {
416     /* 3, store read char len need to minus \b  */
417     if ((readcount == EACH_CHAR) && (consoleCB->fifoIn <= (CONSOLE_FIFO_SIZE - 3))) {
418         if (ch == '\b') {
419             if (!ConsoleFifoEmpty(consoleCB)) {
420                 consoleCB->fifo[--consoleCB->fifoIn] = '\0';
421             }
422         } else {
423             consoleCB->fifo[consoleCB->fifoIn] = (UINT8)ch;
424             consoleCB->fifoIn++;
425         }
426     }
427 }
428 
KillPgrp(UINT16 consoleId)429 VOID KillPgrp(UINT16 consoleId)
430 {
431     if ((consoleId > CONSOLE_NUM) || (consoleId <= 0)) {
432         return;
433     }
434 
435     CONSOLE_CB *consoleCB = g_console[consoleId - 1];
436     /* the default of consoleCB->pgrpId is -1, may not be set yet, avoid killing all processes */
437     if (consoleCB->pgrpId < 0) {
438         return;
439     }
440     (VOID)OsKillLock(consoleCB->pgrpId, SIGINT);
441 }
442 
UserFilepRead(CONSOLE_CB * consoleCB,struct file * filep,const struct file_operations_vfs * fops,CHAR * buffer,size_t bufLen)443 STATIC INT32 UserFilepRead(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops,
444                            CHAR *buffer, size_t bufLen)
445 {
446     INT32 ret;
447     INT32 needreturn = LOS_NOK;
448     CHAR ch;
449     INT32 lastTokenType = STAT_NORMAL_KEY;
450 
451     if (fops->read == NULL) {
452         return -EFAULT;
453     }
454 
455     /* Non-ICANON mode */
456     if ((consoleCB->consoleTermios.c_lflag & ICANON) == 0) {
457         ret = fops->read(filep, buffer, bufLen);
458         return (ret < 0) ? -EPERM : ret;
459     }
460     /* ICANON mode: store data to console buffer,  read data and stored data into console fifo */
461     if (consoleCB->currentLen == 0) {
462         while (1) {
463             ret = fops->read(filep, &ch, EACH_CHAR);
464             if (ret <= 0) {
465                 return ret;
466             }
467 
468             if (IsNeedContinue(consoleCB, ch, &lastTokenType))
469                 continue;
470 
471             switch (ch) {
472                 case '\r':
473                     ch = '\n';
474                 case '\n':
475                     EchoToTerminal(consoleCB, filep, fops, ch);
476                     UserEndOfRead(consoleCB, filep, fops);
477                     ret = ConsoleReadFifo(buffer, consoleCB, bufLen);
478 
479                     needreturn = LOS_OK;
480                     break;
481                 case '\b':
482                 default:
483                     EchoToTerminal(consoleCB, filep, fops, ch);
484                     StoreReadChar(consoleCB, ch, ret);
485                     break;
486             }
487 
488             if (needreturn == LOS_OK)
489                 break;
490         }
491     } else {
492         /* if data is already in console fifo, we return them immediately */
493         ret = ConsoleReadFifo(buffer, consoleCB, bufLen);
494     }
495 
496     return ret;
497 }
498 
FilepRead(struct file * filep,const struct file_operations_vfs * fops,CHAR * buffer,size_t bufLen)499 INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
500 {
501     INT32 ret;
502     if (fops->read == NULL) {
503         return -EFAULT;
504     }
505     /*
506      * adopt uart read function to read data from filep
507      * and write data to buffer (filep is
508      * corresponding to filep of /dev/console)
509      */
510     ret = fops->read(filep, buffer, bufLen);
511     return (ret < 0) ? -EPERM : ret;
512 }
513 
FilepWrite(struct file * filep,const struct file_operations_vfs * fops,const CHAR * buffer,size_t bufLen)514 INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen)
515 {
516     INT32 ret;
517     if (fops->write == NULL) {
518         return -EFAULT;
519     }
520 
521     ret = fops->write(filep, buffer, bufLen);
522     return (ret < 0) ? -EPERM : ret;
523 }
524 
FilepClose(struct file * filep,const struct file_operations_vfs * fops)525 INT32 FilepClose(struct file *filep, const struct file_operations_vfs *fops)
526 {
527     INT32 ret;
528     if ((fops == NULL) || (fops->close == NULL)) {
529         return -EFAULT;
530     }
531 
532     /*
533      * adopt uart close function to open filep (filep is
534      * corresponding to filep of /dev/console)
535      */
536     ret = fops->close(filep);
537     return ret < 0 ? -EPERM : ret;
538 }
539 
FilepIoctl(struct file * filep,const struct file_operations_vfs * fops,INT32 cmd,unsigned long arg)540 INT32 FilepIoctl(struct file *filep, const struct file_operations_vfs *fops, INT32 cmd, unsigned long arg)
541 {
542     INT32 ret;
543     if (fops->ioctl == NULL) {
544         return -EFAULT;
545     }
546 
547     ret = fops->ioctl(filep, cmd, arg);
548     return (ret < 0) ? -EPERM : ret;
549 }
550 
FilepPoll(struct file * filep,const struct file_operations_vfs * fops,poll_table * fds)551 INT32 FilepPoll(struct file *filep, const struct file_operations_vfs *fops, poll_table *fds)
552 {
553     INT32 ret;
554     if (fops->poll == NULL) {
555         return -EFAULT;
556     }
557 
558     /*
559      * adopt uart poll function to poll filep (filep is
560      * corresponding to filep of /dev/serial)
561      */
562     ret = fops->poll(filep, fds);
563     return (ret < 0) ? -EPERM : ret;
564 }
565 
ConsoleOpen(struct file * filep)566 STATIC INT32 ConsoleOpen(struct file *filep)
567 {
568     INT32 ret;
569     UINT32 consoleID;
570     struct file *privFilep = NULL;
571     const struct file_operations_vfs *fileOps = NULL;
572 
573     consoleID = (UINT32)OsConsoleFullpathToID(filep->f_path);
574     if (consoleID == (UINT32)-1) {
575         ret = EPERM;
576         goto ERROUT;
577     }
578     filep->f_priv = g_console[consoleID - 1];
579 
580     ret = GetFilepOps(filep, &privFilep, &fileOps);
581     if (ret != ENOERR) {
582         ret = EINVAL;
583         goto ERROUT;
584     }
585     ret = FilepOpen(privFilep, fileOps);
586     if (ret < 0) {
587         ret = EPERM;
588         goto ERROUT;
589     }
590     return ENOERR;
591 
592 ERROUT:
593     set_errno(ret);
594     return VFS_ERROR;
595 }
596 
ConsoleClose(struct file * filep)597 STATIC INT32 ConsoleClose(struct file *filep)
598 {
599     INT32 ret;
600     struct file *privFilep = NULL;
601     const struct file_operations_vfs *fileOps = NULL;
602 
603     ret = GetFilepOps(filep, &privFilep, &fileOps);
604     if (ret != ENOERR) {
605         ret = EINVAL;
606         goto ERROUT;
607     }
608     ret = FilepClose(privFilep, fileOps);
609     if (ret < 0) {
610         ret = EPERM;
611         goto ERROUT;
612     }
613 
614     return ENOERR;
615 
616 ERROUT:
617     set_errno(ret);
618     return VFS_ERROR;
619 }
620 
DoRead(CONSOLE_CB * consoleCB,CHAR * buffer,size_t bufLen,struct file * privFilep,const struct file_operations_vfs * fileOps)621 STATIC ssize_t DoRead(CONSOLE_CB *consoleCB, CHAR *buffer, size_t bufLen,
622                       struct file *privFilep,
623                       const struct file_operations_vfs *fileOps)
624 {
625     INT32 ret;
626 
627 #ifdef LOSCFG_SHELL
628     if (OsCurrTaskGet()->taskID == consoleCB->shellEntryId) {
629         ret = FilepRead(privFilep, fileOps, buffer, bufLen);
630     } else {
631 #endif
632         (VOID)ConsoleCtrlRightsCapture(consoleCB);
633         ret = UserFilepRead(consoleCB, privFilep, fileOps, buffer, bufLen);
634         (VOID)ConsoleCtrlRightsRelease(consoleCB);
635 #ifdef LOSCFG_SHELL
636     }
637 #endif
638 
639     return ret;
640 }
641 
ConsoleRead(struct file * filep,CHAR * buffer,size_t bufLen)642 STATIC ssize_t ConsoleRead(struct file *filep, CHAR *buffer, size_t bufLen)
643 {
644     INT32 ret;
645     struct file *privFilep = NULL;
646     CONSOLE_CB *consoleCB = NULL;
647     CHAR *sbuffer = NULL;
648     BOOL userBuf = FALSE;
649     const struct file_operations_vfs *fileOps = NULL;
650 
651     if ((buffer == NULL) || (bufLen == 0)) {
652         ret = EINVAL;
653         goto ERROUT;
654     }
655 
656     if (bufLen > CONSOLE_FIFO_SIZE) {
657         bufLen = CONSOLE_FIFO_SIZE;
658     }
659 
660     userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
661     ret = GetFilepOps(filep, &privFilep, &fileOps);
662     if (ret != ENOERR) {
663         ret = -EINVAL;
664         goto ERROUT;
665     }
666     consoleCB = (CONSOLE_CB *)filep->f_priv;
667     if (consoleCB == NULL) {
668         consoleCB = OsGetConsoleByTaskID(OsCurrTaskGet()->taskID);
669         if (consoleCB == NULL) {
670             return -EFAULT;
671         }
672     }
673 
674     /*
675      * shell task use FilepRead function to get data,
676      * user task use UserFilepRead to get data
677      */
678     sbuffer = userBuf ? LOS_MemAlloc(m_aucSysMem0, bufLen) : buffer;
679     if (sbuffer == NULL) {
680         ret = -ENOMEM;
681         goto ERROUT;
682     }
683 
684     ret = DoRead(consoleCB, sbuffer, bufLen, privFilep, fileOps);
685     if (ret < 0) {
686         goto ERROUT;
687     }
688 
689     if (userBuf) {
690         if (LOS_ArchCopyToUser(buffer, sbuffer, bufLen) != 0) {
691             ret = -EFAULT;
692             goto ERROUT;
693         }
694 
695         LOS_MemFree(m_aucSysMem0, sbuffer);
696     }
697 
698     return ret;
699 
700 ERROUT:
701     if ((userBuf) && (sbuffer != NULL)) {
702         LOS_MemFree(m_aucSysMem0, sbuffer);
703     }
704     set_errno(-ret);
705     return VFS_ERROR;
706 }
707 
DoWrite(CirBufSendCB * cirBufSendCB,CHAR * buffer,size_t bufLen)708 STATIC ssize_t DoWrite(CirBufSendCB *cirBufSendCB, CHAR *buffer, size_t bufLen)
709 {
710     INT32 cnt;
711     size_t written = 0;
712     UINT32 intSave;
713 
714 #ifdef LOSCFG_SHELL_DMESG
715     (VOID)OsLogMemcpyRecord(buffer, bufLen);
716     if (OsCheckConsoleLock()) {
717         return 0;
718     }
719 #endif
720 
721     LOS_SpinLockSave(&g_consoleWriteSpinLock, &intSave);
722     while (written < (INT32)bufLen) {
723         /* Transform for CR/LR mode */
724         if ((buffer[written] == '\n') || (buffer[written] == '\r')) {
725             (VOID)LOS_CirBufWrite(&cirBufSendCB->cirBufCB, "\r", 1);
726         }
727 
728         cnt = LOS_CirBufWrite(&cirBufSendCB->cirBufCB, &buffer[written], 1);
729         if (cnt <= 0) {
730             break;
731         }
732         written += cnt;
733     }
734     LOS_SpinUnlockRestore(&g_consoleWriteSpinLock, intSave);
735 
736     /* Log is cached but not printed when a system exception occurs */
737     if (OsGetSystemStatus() == OS_SYSTEM_NORMAL) {
738         (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);
739     }
740 
741     return written;
742 }
743 
ConsoleWrite(struct file * filep,const CHAR * buffer,size_t bufLen)744 STATIC ssize_t ConsoleWrite(struct file *filep, const CHAR *buffer, size_t bufLen)
745 {
746     INT32 ret;
747     CHAR *sbuffer = NULL;
748     BOOL userBuf = FALSE;
749     CirBufSendCB *cirBufSendCB = NULL;
750     struct file *privFilep = NULL;
751     const struct file_operations_vfs *fileOps = NULL;
752 
753     if ((buffer == NULL) || (bufLen == 0)) {
754         ret = EINVAL;
755         goto ERROUT;
756     }
757 
758     if (bufLen > CONSOLE_FIFO_SIZE) {
759         bufLen = CONSOLE_FIFO_SIZE;
760     }
761 
762     userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
763 
764     ret = GetFilepOps(filep, &privFilep, &fileOps);
765     if ((ret != ENOERR) || (fileOps->write == NULL) || (filep->f_priv == NULL)) {
766         ret = EINVAL;
767         goto ERROUT;
768     }
769     cirBufSendCB = ((CONSOLE_CB *)filep->f_priv)->cirBufSendCB;
770 
771     /*
772      * adopt uart open function to read data from buffer
773      * and write data to filep (filep is
774      * corresponding to filep of /dev/console)
775      */
776     sbuffer = userBuf ? LOS_MemAlloc(m_aucSysMem0, bufLen) : (CHAR *)buffer;
777     if (sbuffer == NULL) {
778         ret = ENOMEM;
779         goto ERROUT;
780     }
781 
782     if (userBuf && (LOS_ArchCopyFromUser(sbuffer, buffer, bufLen) != 0)) {
783         ret = EFAULT;
784         goto ERROUT;
785     }
786     ret = DoWrite(cirBufSendCB, sbuffer, bufLen);
787 
788     if (userBuf) {
789         LOS_MemFree(m_aucSysMem0, sbuffer);
790     }
791 
792     return ret;
793 
794 ERROUT:
795     if (userBuf && sbuffer != NULL) {
796         LOS_MemFree(m_aucSysMem0, sbuffer);
797     }
798 
799     set_errno(ret);
800     return VFS_ERROR;
801 }
802 
ConsoleSetSW(CONSOLE_CB * consoleCB,unsigned long arg)803 STATIC INT32 ConsoleSetSW(CONSOLE_CB *consoleCB, unsigned long arg)
804 {
805     struct termios kerTermios;
806     UINT32 intSave;
807 
808     if (LOS_ArchCopyFromUser(&kerTermios, (struct termios *)arg, sizeof(struct termios)) != 0) {
809         return -EFAULT;
810     }
811 
812     LOS_SpinLockSave(&g_consoleSpin, &intSave);
813     (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &kerTermios);
814     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
815     return LOS_OK;
816 }
817 
818 #define DEFAULT_WINDOW_SIZE_COL 80
819 #define DEFAULT_WINDOW_SIZE_ROW 24
ConsoleGetWinSize(unsigned long arg)820 STATIC INT32 ConsoleGetWinSize(unsigned long arg)
821 {
822     struct winsize kws = {
823         .ws_col = DEFAULT_WINDOW_SIZE_COL,
824         .ws_row = DEFAULT_WINDOW_SIZE_ROW
825     };
826 
827     return (LOS_CopyFromKernel((VOID *)arg, sizeof(struct winsize), &kws, sizeof(struct winsize)) != 0) ?
828         -EFAULT : LOS_OK;
829 }
830 
ConsoleGetTermios(unsigned long arg)831 STATIC INT32 ConsoleGetTermios(unsigned long arg)
832 {
833     struct file *filep = NULL;
834     CONSOLE_CB *consoleCB = NULL;
835 
836     INT32 ret = fs_getfilep(0, &filep);
837     if (ret < 0) {
838         return -EPERM;
839     }
840 
841     consoleCB = (CONSOLE_CB *)filep->f_priv;
842     if (consoleCB == NULL) {
843         return -EFAULT;
844     }
845 
846     return (LOS_ArchCopyToUser((VOID *)arg, &consoleCB->consoleTermios, sizeof(struct termios)) != 0) ?
847         -EFAULT : LOS_OK;
848 }
849 
ConsoleSetPgrp(CONSOLE_CB * consoleCB,unsigned long arg)850 INT32 ConsoleSetPgrp(CONSOLE_CB *consoleCB, unsigned long arg)
851 {
852     if (LOS_ArchCopyFromUser(&consoleCB->pgrpId, (INT32 *)(UINTPTR)arg, sizeof(INT32)) != 0) {
853         return -EFAULT;
854     }
855     return LOS_OK;
856 }
857 
ConsoleGetPgrp(CONSOLE_CB * consoleCB,unsigned long arg)858 INT32 ConsoleGetPgrp(CONSOLE_CB *consoleCB, unsigned long arg)
859 {
860     return (LOS_ArchCopyToUser((VOID *)arg, &consoleCB->pgrpId, sizeof(INT32)) != 0) ? -EFAULT : LOS_OK;
861 }
862 
ConsoleIoctl(struct file * filep,INT32 cmd,unsigned long arg)863 STATIC INT32 ConsoleIoctl(struct file *filep, INT32 cmd, unsigned long arg)
864 {
865     INT32 ret;
866     struct file *privFilep = NULL;
867     CONSOLE_CB *consoleCB = NULL;
868     const struct file_operations_vfs *fileOps = NULL;
869 
870     ret = GetFilepOps(filep, &privFilep, &fileOps);
871     if (ret != ENOERR) {
872         ret = EINVAL;
873         goto ERROUT;
874     }
875 
876     if (fileOps->ioctl == NULL) {
877         ret = EFAULT;
878         goto ERROUT;
879     }
880 
881     consoleCB = (CONSOLE_CB *)filep->f_priv;
882     if (consoleCB == NULL) {
883         ret = EINVAL;
884         goto ERROUT;
885     }
886 
887     switch (cmd) {
888         case CONSOLE_CONTROL_RIGHTS_CAPTURE:
889             ret = ConsoleCtrlRightsCapture(consoleCB);
890             break;
891         case CONSOLE_CONTROL_RIGHTS_RELEASE:
892             ret = ConsoleCtrlRightsRelease(consoleCB);
893             break;
894         case CONSOLE_CONTROL_CAPTURE_LINE:
895             ret = ConsoleCtrlCaptureLine(consoleCB);
896             break;
897         case CONSOLE_CONTROL_CAPTURE_CHAR:
898             ret = ConsoleCtrlCaptureChar(consoleCB);
899             break;
900         case CONSOLE_CONTROL_REG_USERTASK:
901             ret = ConsoleTaskReg(consoleCB->consoleID, arg);
902             break;
903         case TIOCGWINSZ:
904             ret = ConsoleGetWinSize(arg);
905             break;
906         case TCSETSW:
907             ret = ConsoleSetSW(consoleCB, arg);
908             break;
909         case TCGETS:
910             ret = ConsoleGetTermios(arg);
911             break;
912         case TIOCGPGRP:
913             ret = ConsoleGetPgrp(consoleCB, arg);
914             break;
915         case TIOCSPGRP:
916             ret = ConsoleSetPgrp(consoleCB, arg);
917             break;
918         default:
919             if ((cmd == UART_CFG_ATTR || cmd == UART_CFG_PRIVATE)
920                 && !LOS_IsUserAddress(arg)) {
921                 ret = EINVAL;
922                 goto ERROUT;
923             }
924             ret = fileOps->ioctl(privFilep, cmd, arg);
925             break;
926     }
927 
928     if (ret < 0) {
929         ret = EPERM;
930         goto ERROUT;
931     }
932 
933     return ret;
934 ERROUT:
935     set_errno(ret);
936     return VFS_ERROR;
937 }
938 
ConsolePoll(struct file * filep,poll_table * fds)939 STATIC INT32 ConsolePoll(struct file *filep, poll_table *fds)
940 {
941     INT32 ret;
942     struct file *privFilep = NULL;
943     const struct file_operations_vfs *fileOps = NULL;
944 
945     ret = GetFilepOps(filep, &privFilep, &fileOps);
946     if (ret != ENOERR) {
947         ret = EINVAL;
948         goto ERROUT;
949     }
950 
951     ret = FilepPoll(privFilep, fileOps, fds);
952     if (ret < 0) {
953         ret = EPERM;
954         goto ERROUT;
955     }
956     return ret;
957 
958 ERROUT:
959     set_errno(ret);
960     return VFS_ERROR;
961 }
962 
963 /* console device driver function structure */
964 STATIC const struct file_operations_vfs g_consoleDevOps = {
965     .open = ConsoleOpen,   /* open */
966     .close = ConsoleClose, /* close */
967     .read = ConsoleRead,   /* read */
968     .write = ConsoleWrite, /* write */
969     .seek = NULL,
970     .ioctl = ConsoleIoctl,
971     .mmap = NULL,
972 #ifndef CONFIG_DISABLE_POLL
973     .poll = ConsolePoll,
974 #endif
975 };
976 
OsConsoleTermiosInit(CONSOLE_CB * consoleCB,const CHAR * deviceName)977 STATIC VOID OsConsoleTermiosInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
978 {
979     struct termios consoleTermios = {0};
980 
981     if ((deviceName != NULL) &&
982         (strlen(deviceName) == strlen(SERIAL)) &&
983         (!strncmp(deviceName, SERIAL, strlen(SERIAL)))) {
984         consoleCB->isNonBlock = SetSerialBlock(consoleCB);
985 
986         /* set console to have a buffer for user */
987         (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
988         consoleTermios.c_lflag |= ICANON | ECHO;
989         consoleTermios.c_cc[VINTR] = 3; /* /003 for ^C */
990         (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
991     }
992 #ifdef LOSCFG_NET_TELNET
993     else if ((deviceName != NULL) &&
994              (strlen(deviceName) == strlen(TELNET)) &&
995              (!strncmp(deviceName, TELNET, strlen(TELNET)))) {
996         consoleCB->isNonBlock = SetTelnetBlock(consoleCB);
997         /* set console to have a buffer for user */
998         (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
999         consoleTermios.c_lflag |= ICANON | ECHO;
1000         consoleTermios.c_cc[VINTR] = 3; /* /003 for ^C */
1001         (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
1002     }
1003 #endif
1004 }
1005 
OsConsoleFileInit(CONSOLE_CB * consoleCB)1006 STATIC INT32 OsConsoleFileInit(CONSOLE_CB *consoleCB)
1007 {
1008     INT32 ret;
1009     struct Vnode *vnode = NULL;
1010     struct file *filep = NULL;
1011 
1012     VnodeHold();
1013     ret = VnodeLookup(consoleCB->name, &vnode, 0);
1014     if (ret != LOS_OK) {
1015         ret = EACCES;
1016         goto ERROUT;
1017     }
1018 
1019     filep = files_allocate(vnode, O_RDWR, 0, consoleCB, FILE_START_FD);
1020     if (filep == NULL) {
1021         ret = EMFILE;
1022         goto ERROUT;
1023     }
1024     filep->ops = (struct file_operations_vfs *)((struct drv_data *)vnode->data)->ops;
1025     consoleCB->fd = filep->fd;
1026 
1027 ERROUT:
1028     VnodeDrop();
1029     return ret;
1030 }
1031 
1032 /*
1033  * Initialized console control platform so that when we operate /dev/console
1034  * as if we are operating /dev/ttyS0 (uart0).
1035  */
OsConsoleDevInit(CONSOLE_CB * consoleCB,const CHAR * deviceName)1036 STATIC INT32 OsConsoleDevInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
1037 {
1038     INT32 ret;
1039     struct file *filep = NULL;
1040     struct Vnode *vnode = NULL;
1041     struct file_operations_vfs *devOps = NULL;
1042 
1043     /* allocate memory for filep,in order to unchange the value of filep */
1044     filep = (struct file *)LOS_MemAlloc(m_aucSysMem0, sizeof(struct file));
1045     if (filep == NULL) {
1046         ret = ENOMEM;
1047         goto ERROUT;
1048     }
1049 
1050     VnodeHold();
1051     ret = VnodeLookup(deviceName, &vnode, V_DUMMY);
1052     VnodeDrop(); // not correct, but can't fix perfectly here
1053     if (ret != LOS_OK) {
1054         ret = EACCES;
1055         PRINTK("!! can not find %s\n", consoleCB->name);
1056         goto ERROUT;
1057     }
1058 
1059     consoleCB->devVnode = vnode;
1060 
1061     /*
1062      * initialize the console filep which is associated with /dev/console,
1063      * assign the uart0 vnode of /dev/ttyS0 to console inod of /dev/console,
1064      * then we can operate console's filep as if we operate uart0 filep of
1065      * /dev/ttyS0.
1066      */
1067     (VOID)memset_s(filep, sizeof(struct file), 0, sizeof(struct file));
1068     filep->f_oflags = O_RDWR;
1069     filep->f_pos = 0;
1070     filep->f_vnode = vnode;
1071     filep->f_path = NULL;
1072     filep->f_priv = NULL;
1073     /*
1074      * Use filep to connect console and uart, we can find uart driver function through filep.
1075      * now we can operate /dev/console to operate /dev/ttyS0 through filep.
1076      */
1077     devOps = (struct file_operations_vfs *)((struct drv_data*)vnode->data)->ops;
1078     if (devOps != NULL && devOps->open != NULL) {
1079         (VOID)devOps->open(filep);
1080     } else {
1081         ret = ENOSYS;
1082         goto ERROUT;
1083     }
1084 
1085     ret = register_driver(consoleCB->name, &g_consoleDevOps, DEFFILEMODE, filep);
1086     if (ret != LOS_OK) {
1087         goto ERROUT;
1088     }
1089 
1090     return LOS_OK;
1091 
1092 ERROUT:
1093      if (filep) {
1094         (VOID)LOS_MemFree(m_aucSysMem0, filep);
1095     }
1096 
1097     set_errno(ret);
1098     return LOS_NOK;
1099 }
1100 
OsConsoleDevDeinit(const CONSOLE_CB * consoleCB)1101 STATIC UINT32 OsConsoleDevDeinit(const CONSOLE_CB *consoleCB)
1102 {
1103     return unregister_driver(consoleCB->name);
1104 }
1105 
ConsoleCirBufCreate(VOID)1106 STATIC CirBufSendCB *ConsoleCirBufCreate(VOID)
1107 {
1108     UINT32 ret;
1109     CHAR *fifo = NULL;
1110     CirBufSendCB *cirBufSendCB = NULL;
1111     CirBuf *cirBufCB = NULL;
1112 
1113     cirBufSendCB = (CirBufSendCB *)LOS_MemAlloc(m_aucSysMem0, sizeof(CirBufSendCB));
1114     if (cirBufSendCB == NULL) {
1115         return NULL;
1116     }
1117     (VOID)memset_s(cirBufSendCB, sizeof(CirBufSendCB), 0, sizeof(CirBufSendCB));
1118 
1119     fifo = (CHAR *)LOS_MemAlloc(m_aucSysMem0, CONSOLE_CIRCBUF_SIZE);
1120     if (fifo == NULL) {
1121         goto ERROR_WITH_SENDCB;
1122     }
1123     (VOID)memset_s(fifo, CONSOLE_CIRCBUF_SIZE, 0, CONSOLE_CIRCBUF_SIZE);
1124 
1125     cirBufCB = &cirBufSendCB->cirBufCB;
1126     ret = LOS_CirBufInit(cirBufCB, fifo, CONSOLE_CIRCBUF_SIZE);
1127     if (ret != LOS_OK) {
1128         goto ERROR_WITH_FIFO;
1129     }
1130 
1131     (VOID)LOS_EventInit(&cirBufSendCB->sendEvent);
1132     return cirBufSendCB;
1133 
1134 ERROR_WITH_FIFO:
1135     (VOID)LOS_MemFree(m_aucSysMem0, cirBufCB->fifo);
1136 ERROR_WITH_SENDCB:
1137     (VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);
1138     return NULL;
1139 }
1140 
ConsoleCirBufDelete(CirBufSendCB * cirBufSendCB)1141 STATIC VOID ConsoleCirBufDelete(CirBufSendCB *cirBufSendCB)
1142 {
1143     CirBuf *cirBufCB = &cirBufSendCB->cirBufCB;
1144 
1145     (VOID)LOS_MemFree(m_aucSysMem0, cirBufCB->fifo);
1146     LOS_CirBufDeinit(cirBufCB);
1147     (VOID)LOS_EventDestroy(&cirBufSendCB->sendEvent);
1148     (VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);
1149 }
1150 
OsConsoleBufInit(CONSOLE_CB * consoleCB)1151 STATIC UINT32 OsConsoleBufInit(CONSOLE_CB *consoleCB)
1152 {
1153     UINT32 ret;
1154     TSK_INIT_PARAM_S initParam = {0};
1155 
1156     consoleCB->cirBufSendCB = ConsoleCirBufCreate();
1157     if (consoleCB->cirBufSendCB == NULL) {
1158         return LOS_NOK;
1159     }
1160 
1161     initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ConsoleSendTask;
1162     initParam.usTaskPrio   = SHELL_TASK_PRIORITY;
1163     initParam.auwArgs[0]   = (UINTPTR)consoleCB;
1164     initParam.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
1165     initParam.pcName = (consoleCB->consoleID == CONSOLE_SERIAL) ? "SendToSer" : "SendToTelnet";
1166     initParam.uwResved     = LOS_TASK_STATUS_DETACHED;
1167 
1168     ret = LOS_TaskCreate(&consoleCB->sendTaskID, &initParam);
1169     if (ret != LOS_OK) {
1170         ConsoleCirBufDelete(consoleCB->cirBufSendCB);
1171         consoleCB->cirBufSendCB = NULL;
1172         return LOS_NOK;
1173     }
1174     (VOID)LOS_EventRead(&consoleCB->cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_RUNNING,
1175                         LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
1176 
1177     return LOS_OK;
1178 }
1179 
OsConsoleBufDeinit(CONSOLE_CB * consoleCB)1180 STATIC VOID OsConsoleBufDeinit(CONSOLE_CB *consoleCB)
1181 {
1182     CirBufSendCB *cirBufSendCB = consoleCB->cirBufSendCB;
1183 
1184     consoleCB->cirBufSendCB = NULL;
1185     (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_EXIT);
1186 }
1187 
OsConsoleCBInit(UINT32 consoleID)1188 STATIC CONSOLE_CB *OsConsoleCBInit(UINT32 consoleID)
1189 {
1190     CONSOLE_CB *consoleCB = (CONSOLE_CB *)LOS_MemAlloc((VOID *)m_aucSysMem0, sizeof(CONSOLE_CB));
1191     if (consoleCB == NULL) {
1192         return NULL;
1193     }
1194     (VOID)memset_s(consoleCB, sizeof(CONSOLE_CB), 0, sizeof(CONSOLE_CB));
1195 
1196     consoleCB->consoleID = consoleID;
1197     consoleCB->pgrpId = -1;
1198     consoleCB->shellEntryId = SHELL_ENTRYID_INVALID; /* initialize shellEntryId to an invalid value */
1199     consoleCB->name = LOS_MemAlloc((VOID *)m_aucSysMem0, CONSOLE_NAMELEN);
1200     if (consoleCB->name == NULL) {
1201         PRINT_ERR("consoleCB->name malloc failed\n");
1202         (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB);
1203         return NULL;
1204     }
1205     return consoleCB;
1206 }
1207 
OsConsoleCBDeinit(CONSOLE_CB * consoleCB)1208 STATIC VOID OsConsoleCBDeinit(CONSOLE_CB *consoleCB)
1209 {
1210     (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB->name);
1211     consoleCB->name = NULL;
1212     (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB);
1213 }
1214 
OsConsoleCreate(UINT32 consoleID,const CHAR * deviceName)1215 STATIC CONSOLE_CB *OsConsoleCreate(UINT32 consoleID, const CHAR *deviceName)
1216 {
1217     INT32 ret;
1218     CONSOLE_CB *consoleCB = OsConsoleCBInit(consoleID);
1219     if (consoleCB == NULL) {
1220         PRINT_ERR("console malloc error.\n");
1221         return NULL;
1222     }
1223 
1224     ret = snprintf_s(consoleCB->name, CONSOLE_NAMELEN, CONSOLE_NAMELEN - 1,
1225                      "%s%u", CONSOLE, consoleCB->consoleID);
1226     if (ret == -1) {
1227         PRINT_ERR("consoleCB->name snprintf_s failed\n");
1228         goto ERR_WITH_NAME;
1229     }
1230 
1231     ret = (INT32)OsConsoleBufInit(consoleCB);
1232     if (ret != LOS_OK) {
1233         PRINT_ERR("console OsConsoleBufInit error. %d\n", ret);
1234         goto ERR_WITH_NAME;
1235     }
1236 
1237     ret = (INT32)LOS_SemCreate(1, &consoleCB->consoleSem);
1238     if (ret != LOS_OK) {
1239         PRINT_ERR("create sem for uart failed\n");
1240         goto ERR_WITH_BUF;
1241     }
1242 
1243     ret = OsConsoleDevInit(consoleCB, deviceName);
1244     if (ret != LOS_OK) {
1245         PRINT_ERR("console OsConsoleDevInit error. %d\n", ret);
1246         goto ERR_WITH_SEM;
1247     }
1248 
1249     ret = OsConsoleFileInit(consoleCB);
1250     if (ret != LOS_OK) {
1251         PRINT_ERR("console OsConsoleFileInit error. %d\n", ret);
1252         goto ERR_WITH_DEV;
1253     }
1254 
1255     OsConsoleTermiosInit(consoleCB, deviceName);
1256     return consoleCB;
1257 
1258 ERR_WITH_DEV:
1259     ret = (INT32)OsConsoleDevDeinit(consoleCB);
1260     if (ret != LOS_OK) {
1261         PRINT_ERR("OsConsoleDevDeinit failed!\n");
1262     }
1263 ERR_WITH_SEM:
1264     (VOID)LOS_SemDelete(consoleCB->consoleSem);
1265 ERR_WITH_BUF:
1266     OsConsoleBufDeinit(consoleCB);
1267 ERR_WITH_NAME:
1268     OsConsoleCBDeinit(consoleCB);
1269     return NULL;
1270 }
1271 
OsConsoleDelete(CONSOLE_CB * consoleCB)1272 STATIC UINT32 OsConsoleDelete(CONSOLE_CB *consoleCB)
1273 {
1274     UINT32 ret;
1275 
1276     (VOID)files_close(consoleCB->fd);
1277     ret = OsConsoleDevDeinit(consoleCB);
1278     if (ret != LOS_OK) {
1279         PRINT_ERR("OsConsoleDevDeinit failed!\n");
1280     }
1281     OsConsoleBufDeinit((CONSOLE_CB *)consoleCB);
1282     (VOID)LOS_SemDelete(consoleCB->consoleSem);
1283     (VOID)LOS_MemFree(m_aucSysMem0, consoleCB->name);
1284     consoleCB->name = NULL;
1285     (VOID)LOS_MemFree(m_aucSysMem0, consoleCB);
1286 
1287     return ret;
1288 }
1289 
1290 /* Initialized system console and return stdinfd stdoutfd stderrfd */
system_console_init(const CHAR * deviceName)1291 INT32 system_console_init(const CHAR *deviceName)
1292 {
1293 #ifdef LOSCFG_SHELL
1294     UINT32 ret;
1295 #endif
1296     INT32 consoleID;
1297     UINT32 intSave;
1298     CONSOLE_CB *consoleCB = NULL;
1299 
1300     consoleID = OsGetConsoleID(deviceName);
1301     if (consoleID == -1) {
1302         PRINT_ERR("device is full.\n");
1303         return VFS_ERROR;
1304     }
1305 
1306     consoleCB = OsConsoleCreate((UINT32)consoleID, deviceName);
1307     if (consoleCB == NULL) {
1308         PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1309         return VFS_ERROR;
1310     }
1311 
1312     LOS_SpinLockSave(&g_consoleSpin, &intSave);
1313     g_console[consoleID - 1] = consoleCB;
1314     if (OsCurrTaskGet() != NULL) {
1315         g_taskConsoleIDArray[OsCurrTaskGet()->taskID] = (UINT8)consoleID;
1316     }
1317     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1318 
1319 #ifdef LOSCFG_SHELL
1320     ret = OsShellInit(consoleID);
1321     if (ret != LOS_OK) {
1322         PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1323         LOS_SpinLockSave(&g_consoleSpin, &intSave);
1324         (VOID)OsConsoleDelete(consoleCB);
1325         g_console[consoleID - 1] = NULL;
1326         if (OsCurrTaskGet() != NULL) {
1327             g_taskConsoleIDArray[OsCurrTaskGet()->taskID] = 0;
1328         }
1329         LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1330         return VFS_ERROR;
1331     }
1332 #endif
1333 
1334     return ENOERR;
1335 }
1336 
system_console_deinit(const CHAR * deviceName)1337 INT32 system_console_deinit(const CHAR *deviceName)
1338 {
1339     UINT32 ret;
1340     CONSOLE_CB *consoleCB = NULL;
1341     UINT32 taskIdx;
1342     LosTaskCB *taskCB = NULL;
1343     UINT32 intSave;
1344 
1345     consoleCB = OsGetConsoleByDevice(deviceName);
1346     if (consoleCB == NULL) {
1347         return VFS_ERROR;
1348     }
1349 
1350 #ifdef LOSCFG_SHELL
1351     (VOID)OsShellDeinit((INT32)consoleCB->consoleID);
1352 #endif
1353 
1354     LOS_SpinLockSave(&g_consoleSpin, &intSave);
1355     /* Redirect all tasks to serial as telnet was unavailable after deinitializing */
1356     for (taskIdx = 0; taskIdx < g_taskMaxNum; taskIdx++) {
1357         taskCB = ((LosTaskCB *)g_taskCBArray) + taskIdx;
1358         if (OsTaskIsUnused(taskCB)) {
1359             continue;
1360         } else {
1361             g_taskConsoleIDArray[taskCB->taskID] = CONSOLE_SERIAL;
1362         }
1363     }
1364     g_console[consoleCB->consoleID - 1] = NULL;
1365     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1366 
1367     ret = OsConsoleDelete(consoleCB);
1368     if (ret != LOS_OK) {
1369         PRINT_ERR("%s, Failed to system_console_deinit\n", __FUNCTION__);
1370         return VFS_ERROR;
1371     }
1372 
1373     return ENOERR;
1374 }
1375 
ConsoleEnable(VOID)1376 BOOL ConsoleEnable(VOID)
1377 {
1378     INT32 consoleID;
1379 
1380     if (OsCurrTaskGet() != NULL) {
1381         consoleID = g_taskConsoleIDArray[OsCurrTaskGet()->taskID];
1382         if (g_uart_fputc_en == 0) {
1383             if ((g_console[CONSOLE_TELNET - 1] != NULL) && OsPreemptable()) {
1384                 return TRUE;
1385             }
1386         }
1387 
1388         if (consoleID == 0) {
1389             return FALSE;
1390         } else if ((consoleID == CONSOLE_TELNET) || (consoleID == CONSOLE_SERIAL)) {
1391             return ((OsGetSystemStatus() == OS_SYSTEM_NORMAL) && !OsPreemptable()) ? FALSE : TRUE;
1392         }
1393 #if defined (LOSCFG_DRIVERS_USB_SERIAL_GADGET) || defined (LOSCFG_DRIVERS_USB_ETH_SER_GADGET)
1394         else if ((SerialTypeGet() == SERIAL_TYPE_USBTTY_DEV) && (userial_mask_get() == 1)) {
1395             return TRUE;
1396         }
1397 #endif
1398     }
1399 
1400     return FALSE;
1401 }
1402 
IsShellEntryRunning(UINT32 shellEntryId)1403 BOOL IsShellEntryRunning(UINT32 shellEntryId)
1404 {
1405     LosTaskCB *taskCB = NULL;
1406     if (shellEntryId == SHELL_ENTRYID_INVALID) {
1407         return FALSE;
1408     }
1409     taskCB = OsGetTaskCB(shellEntryId);
1410     return !OsTaskIsUnused(taskCB) &&
1411            (strlen(taskCB->taskName) == SHELL_ENTRY_NAME_LEN &&
1412             strncmp(taskCB->taskName, SHELL_ENTRY_NAME, SHELL_ENTRY_NAME_LEN) == 0);
1413 }
1414 
ConsoleTaskReg(INT32 consoleID,UINT32 taskID)1415 INT32 ConsoleTaskReg(INT32 consoleID, UINT32 taskID)
1416 {
1417     UINT32 intSave;
1418 
1419     LOS_SpinLockSave(&g_consoleSpin, &intSave);
1420     if (!IsShellEntryRunning(g_console[consoleID - 1]->shellEntryId)) {
1421         g_console[consoleID - 1]->shellEntryId = taskID;
1422         LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1423         (VOID)OsSetCurrProcessGroupID(OsGetUserInitProcessID());
1424         return LOS_OK;
1425     }
1426     LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1427     return (g_console[consoleID - 1]->shellEntryId == taskID) ? LOS_OK : LOS_NOK;
1428 }
1429 
SetSerialNonBlock(const CONSOLE_CB * consoleCB)1430 BOOL SetSerialNonBlock(const CONSOLE_CB *consoleCB)
1431 {
1432     if (consoleCB == NULL) {
1433         PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1434         return FALSE;
1435     }
1436     return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_SERIAL, CONSOLE_RD_NONBLOCK) == 0;
1437 }
1438 
SetSerialBlock(const CONSOLE_CB * consoleCB)1439 BOOL SetSerialBlock(const CONSOLE_CB *consoleCB)
1440 {
1441     if (consoleCB == NULL) {
1442         PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1443         return TRUE;
1444     }
1445     return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_SERIAL, CONSOLE_RD_BLOCK) != 0;
1446 }
1447 
SetTelnetNonBlock(const CONSOLE_CB * consoleCB)1448 BOOL SetTelnetNonBlock(const CONSOLE_CB *consoleCB)
1449 {
1450     if (consoleCB == NULL) {
1451         PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1452         return FALSE;
1453     }
1454     return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_TELNET, CONSOLE_RD_NONBLOCK) == 0;
1455 }
1456 
SetTelnetBlock(const CONSOLE_CB * consoleCB)1457 BOOL SetTelnetBlock(const CONSOLE_CB *consoleCB)
1458 {
1459     if (consoleCB == NULL) {
1460         PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1461         return TRUE;
1462     }
1463     return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_TELNET, CONSOLE_RD_BLOCK) != 0;
1464 }
1465 
is_nonblock(const CONSOLE_CB * consoleCB)1466 BOOL is_nonblock(const CONSOLE_CB *consoleCB)
1467 {
1468     if (consoleCB == NULL) {
1469         PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1470         return FALSE;
1471     }
1472     return consoleCB->isNonBlock;
1473 }
1474 
ConsoleUpdateFd(VOID)1475 INT32 ConsoleUpdateFd(VOID)
1476 {
1477     INT32 consoleID;
1478 
1479     if (OsCurrTaskGet() != NULL) {
1480         consoleID = g_taskConsoleIDArray[(OsCurrTaskGet())->taskID];
1481     } else {
1482         return -1;
1483     }
1484 
1485     if (g_uart_fputc_en == 0) {
1486         if (g_console[CONSOLE_TELNET - 1] != NULL) {
1487             consoleID = CONSOLE_TELNET;
1488         }
1489     } else if (consoleID == 0) {
1490         if (g_console[CONSOLE_SERIAL - 1] != NULL) {
1491             consoleID = CONSOLE_SERIAL;
1492         } else if (g_console[CONSOLE_TELNET - 1] != NULL) {
1493             consoleID = CONSOLE_TELNET;
1494         } else {
1495             PRINTK("No console dev used.\n");
1496             return -1;
1497         }
1498     }
1499 
1500     return (g_console[consoleID - 1] != NULL) ? g_console[consoleID - 1]->fd : -1;
1501 }
1502 
OsGetConsoleByID(INT32 consoleID)1503 CONSOLE_CB *OsGetConsoleByID(INT32 consoleID)
1504 {
1505     if (consoleID != CONSOLE_TELNET) {
1506         consoleID = CONSOLE_SERIAL;
1507     }
1508     return g_console[consoleID - 1];
1509 }
1510 
OsGetConsoleByTaskID(UINT32 taskID)1511 CONSOLE_CB *OsGetConsoleByTaskID(UINT32 taskID)
1512 {
1513     INT32 consoleID = g_taskConsoleIDArray[taskID];
1514 
1515     return OsGetConsoleByID(consoleID);
1516 }
1517 
OsSetConsoleID(UINT32 newTaskID,UINT32 curTaskID)1518 VOID OsSetConsoleID(UINT32 newTaskID, UINT32 curTaskID)
1519 {
1520     if ((newTaskID >= LOSCFG_BASE_CORE_TSK_LIMIT) || (curTaskID >= LOSCFG_BASE_CORE_TSK_LIMIT)) {
1521         return;
1522     }
1523 
1524     g_taskConsoleIDArray[newTaskID] = g_taskConsoleIDArray[curTaskID];
1525 }
1526 
WriteToTerminal(const CONSOLE_CB * consoleCB,const CHAR * buffer,size_t bufLen)1527 STATIC ssize_t WriteToTerminal(const CONSOLE_CB *consoleCB, const CHAR *buffer, size_t bufLen)
1528 {
1529     INT32 ret, fd;
1530     INT32 cnt = 0;
1531     struct file *privFilep = NULL;
1532     struct file *filep = NULL;
1533     const struct file_operations_vfs *fileOps = NULL;
1534 
1535     fd = consoleCB->fd;
1536     ret = fs_getfilep(fd, &filep);
1537     if (ret < 0) {
1538         ret = -EPERM;
1539         goto ERROUT;
1540     }
1541     ret = GetFilepOps(filep, &privFilep, &fileOps);
1542     if (ret != ENOERR) {
1543         ret = -EINVAL;
1544         goto ERROUT;
1545     }
1546 
1547     if ((fileOps == NULL) || (fileOps->write == NULL)) {
1548         ret = EFAULT;
1549         goto ERROUT;
1550     }
1551     (VOID)fileOps->write(privFilep, buffer, bufLen);
1552 
1553     return cnt;
1554 
1555 ERROUT:
1556     set_errno(ret);
1557     return VFS_ERROR;
1558 }
1559 
ConsoleSendTask(UINTPTR param)1560 STATIC UINT32 ConsoleSendTask(UINTPTR param)
1561 {
1562     CONSOLE_CB *consoleCB = (CONSOLE_CB *)param;
1563     CirBufSendCB *cirBufSendCB = consoleCB->cirBufSendCB;
1564     CirBuf *cirBufCB = &cirBufSendCB->cirBufCB;
1565     UINT32 ret, size;
1566     CHAR *buf = NULL;
1567 
1568     (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_RUNNING);
1569 
1570     while (1) {
1571         ret = LOS_EventRead(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT | CONSOLE_SEND_TASK_EXIT,
1572                             LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
1573         if (ret == CONSOLE_CIRBUF_EVENT) {
1574             size =  LOS_CirBufUsedSize(cirBufCB);
1575             if (size == 0) {
1576                 continue;
1577             }
1578             buf = (CHAR *)LOS_MemAlloc(m_aucSysMem1, size + 1);
1579             if (buf == NULL) {
1580                 continue;
1581             }
1582             (VOID)memset_s(buf, size + 1, 0, size + 1);
1583 
1584             (VOID)LOS_CirBufRead(cirBufCB, buf, size);
1585 
1586             (VOID)WriteToTerminal(consoleCB, buf, size);
1587             (VOID)LOS_MemFree(m_aucSysMem1, buf);
1588         } else if (ret == CONSOLE_SEND_TASK_EXIT) {
1589             break;
1590         }
1591     }
1592 
1593     ConsoleCirBufDelete(cirBufSendCB);
1594     return LOS_OK;
1595 }
1596 
1597 #ifdef LOSCFG_KERNEL_SMP
OsWaitConsoleSendTaskPend(UINT32 taskID)1598 VOID OsWaitConsoleSendTaskPend(UINT32 taskID)
1599 {
1600     UINT32 i;
1601     CONSOLE_CB *console = NULL;
1602     LosTaskCB *taskCB = NULL;
1603     INT32 waitTime = 3000; /* 3000: 3 seconds */
1604 
1605     for (i = 0; i < CONSOLE_NUM; i++) {
1606         console = g_console[i];
1607         if (console == NULL) {
1608             continue;
1609         }
1610 
1611         if (OS_TID_CHECK_INVALID(console->sendTaskID)) {
1612             continue;
1613         }
1614 
1615         taskCB = OS_TCB_FROM_TID(console->sendTaskID);
1616         while ((waitTime > 0) && (taskCB->taskEvent == NULL) && (taskID != console->sendTaskID)) {
1617             LOS_Mdelay(1); /* 1: wait console task pend */
1618             --waitTime;
1619         }
1620     }
1621 }
1622 
OsWakeConsoleSendTask(VOID)1623 VOID OsWakeConsoleSendTask(VOID)
1624 {
1625     UINT32 i;
1626     CONSOLE_CB *console = NULL;
1627 
1628     for (i = 0; i < CONSOLE_NUM; i++) {
1629         console = g_console[i];
1630         if (console == NULL) {
1631             continue;
1632         }
1633 
1634         if (console->cirBufSendCB != NULL) {
1635             (VOID)LOS_EventWrite(&console->cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);
1636         }
1637     }
1638 }
1639 #endif
1640 
1641