1 /******************************************************************************
2  *
3  * Module Name: osgendbg - Generic debugger command singalling
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acdebug.h"
47 
48 
49 #define _COMPONENT          ACPI_CA_DEBUGGER
50         ACPI_MODULE_NAME    ("osgendbg")
51 
52 
53 /* Local prototypes */
54 
55 static void
56 AcpiDbRunRemoteDebugger (
57     char                    *BatchBuffer);
58 
59 
60 static ACPI_MUTEX           AcpiGbl_DbCommandReady;
61 static ACPI_MUTEX           AcpiGbl_DbCommandComplete;
62 static BOOLEAN              AcpiGbl_DbCommandSignalsInitialized = FALSE;
63 
64 /******************************************************************************
65  *
66  * FUNCTION:    AcpiDbRunRemoteDebugger
67  *
68  * PARAMETERS:  BatchBuffer         - Buffer containing commands running in
69  *                                    the batch mode
70  *
71  * RETURN:      None
72  *
73  * DESCRIPTION: Run multi-threading debugger remotely
74  *
75  *****************************************************************************/
76 
77 static void
78 AcpiDbRunRemoteDebugger (
79     char                    *BatchBuffer)
80 {
81     ACPI_STATUS             Status;
82     char                    *Ptr = BatchBuffer;
83     char                    *Cmd = Ptr;
84 
85 
86     while (!AcpiGbl_DbTerminateLoop)
87     {
88         if (BatchBuffer)
89         {
90             if (*Ptr)
91             {
92                 while (*Ptr)
93                 {
94                     if (*Ptr == ',')
95                     {
96                         /* Convert commas to spaces */
97                         *Ptr = ' ';
98                     }
99                     else if (*Ptr == ';')
100                     {
101                         *Ptr = '\0';
102                         continue;
103                     }
104 
105                     Ptr++;
106                 }
107 
108                 strncpy (AcpiGbl_DbLineBuf, Cmd, ACPI_DB_LINE_BUFFER_SIZE);
109                 Ptr++;
110                 Cmd = Ptr;
111             }
112             else
113             {
114                 return;
115             }
116         }
117         else
118         {
119             /* Force output to console until a command is entered */
120 
121             AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
122 
123             /* Different prompt if method is executing */
124 
125             if (!AcpiGbl_MethodExecuting)
126             {
127                 AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
128             }
129             else
130             {
131                 AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
132             }
133 
134             /* Get the user input line */
135 
136             Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
137                 ACPI_DB_LINE_BUFFER_SIZE, NULL);
138             if (ACPI_FAILURE (Status))
139             {
140                 return;
141             }
142         }
143 
144         /*
145          * Signal the debug thread that we have a command to execute,
146          * and wait for the command to complete.
147          */
148         AcpiOsReleaseMutex (AcpiGbl_DbCommandReady);
149 
150         Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandComplete,
151             ACPI_WAIT_FOREVER);
152         if (ACPI_FAILURE (Status))
153         {
154             return;
155         }
156     }
157 }
158 
159 
160 /******************************************************************************
161  *
162  * FUNCTION:    AcpiOsWaitCommandReady
163  *
164  * PARAMETERS:  None
165  *
166  * RETURN:      Status
167  *
168  * DESCRIPTION: Negotiate with the debugger foreground thread (the user
169  *              thread) to wait the readiness of a command.
170  *
171  *****************************************************************************/
172 
173 ACPI_STATUS
174 AcpiOsWaitCommandReady (
175     void)
176 {
177     ACPI_STATUS             Status = AE_OK;
178 
179 
180     if (AcpiGbl_DebuggerConfiguration == DEBUGGER_MULTI_THREADED)
181     {
182         Status = AE_TIME;
183 
184         while (Status == AE_TIME)
185         {
186             if (AcpiGbl_DbTerminateLoop)
187             {
188                 Status = AE_CTRL_TERMINATE;
189             }
190             else
191             {
192                 Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandReady, 1000);
193             }
194         }
195     }
196     else
197     {
198         /* Force output to console until a command is entered */
199 
200         AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
201 
202         /* Different prompt if method is executing */
203 
204         if (!AcpiGbl_MethodExecuting)
205         {
206             AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
207         }
208         else
209         {
210             AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
211         }
212 
213         /* Get the user input line */
214 
215         Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
216             ACPI_DB_LINE_BUFFER_SIZE, NULL);
217     }
218 
219     if (ACPI_FAILURE (Status) && Status != AE_CTRL_TERMINATE)
220     {
221         ACPI_EXCEPTION ((AE_INFO, Status,
222             "While parsing/handling command line"));
223     }
224     return (Status);
225 }
226 
227 
228 /******************************************************************************
229  *
230  * FUNCTION:    AcpiOsNotifyCommandComplete
231  *
232  * PARAMETERS:  void
233  *
234  * RETURN:      Status
235  *
236  * DESCRIPTION: Negotiate with the debugger foreground thread (the user
237  *              thread) to notify the completion of a command.
238  *
239  *****************************************************************************/
240 
241 ACPI_STATUS
242 AcpiOsNotifyCommandComplete (
243     void)
244 {
245 
246     if (AcpiGbl_DebuggerConfiguration == DEBUGGER_MULTI_THREADED)
247     {
248         AcpiOsReleaseMutex (AcpiGbl_DbCommandComplete);
249     }
250     return (AE_OK);
251 }
252 
253 
254 /******************************************************************************
255  *
256  * FUNCTION:    AcpiOsInitializeDebugger
257  *
258  * PARAMETERS:  None
259  *
260  * RETURN:      Status
261  *
262  * DESCRIPTION: Initialize OSPM specific part of the debugger
263  *
264  *****************************************************************************/
265 
266 ACPI_STATUS
267 AcpiOsInitializeDebugger (
268     void)
269 {
270     ACPI_STATUS             Status;
271 
272 
273     /* Create command signals */
274 
275     Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandReady);
276     if (ACPI_FAILURE (Status))
277     {
278         return (Status);
279     }
280     Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandComplete);
281     if (ACPI_FAILURE (Status))
282     {
283         goto ErrorReady;
284     }
285 
286     /* Initialize the states of the command signals */
287 
288     Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandComplete,
289         ACPI_WAIT_FOREVER);
290     if (ACPI_FAILURE (Status))
291     {
292         goto ErrorComplete;
293     }
294     Status = AcpiOsAcquireMutex (AcpiGbl_DbCommandReady,
295         ACPI_WAIT_FOREVER);
296     if (ACPI_FAILURE (Status))
297     {
298         goto ErrorComplete;
299     }
300 
301     AcpiGbl_DbCommandSignalsInitialized = TRUE;
302     return (Status);
303 
304 ErrorComplete:
305     AcpiOsDeleteMutex (AcpiGbl_DbCommandComplete);
306 ErrorReady:
307     AcpiOsDeleteMutex (AcpiGbl_DbCommandReady);
308     return (Status);
309 }
310 
311 
312 /******************************************************************************
313  *
314  * FUNCTION:    AcpiOsTerminateDebugger
315  *
316  * PARAMETERS:  None
317  *
318  * RETURN:      None
319  *
320  * DESCRIPTION: Terminate signals used by the multi-threading debugger
321  *
322  *****************************************************************************/
323 
324 void
325 AcpiOsTerminateDebugger (
326     void)
327 {
328 
329     if (AcpiGbl_DbCommandSignalsInitialized)
330     {
331         AcpiOsDeleteMutex (AcpiGbl_DbCommandReady);
332         AcpiOsDeleteMutex (AcpiGbl_DbCommandComplete);
333     }
334 }
335 
336 
337 /******************************************************************************
338  *
339  * FUNCTION:    AcpiRunDebugger
340  *
341  * PARAMETERS:  BatchBuffer         - Buffer containing commands running in
342  *                                    the batch mode
343  *
344  * RETURN:      None
345  *
346  * DESCRIPTION: Run a local/remote debugger
347  *
348  *****************************************************************************/
349 
350 void
351 AcpiRunDebugger (
352     char                    *BatchBuffer)
353 {
354     /* Check for single or multithreaded debug */
355 
356     if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED)
357     {
358         AcpiDbRunRemoteDebugger (BatchBuffer);
359     }
360     else
361     {
362         AcpiDbUserCommands ();
363     }
364 }
365 
366 ACPI_EXPORT_SYMBOL (AcpiRunDebugger)
367